{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-03T06:56:21.485119Z",
     "start_time": "2020-09-03T06:56:20.966286Z"
    }
   },
   "outputs": [],
   "source": [
    "import pickle\n",
    "import argparse\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import networkx as nx\n",
    "import torch\n",
    "import random\n",
    "import math\n",
    "from scipy.io import mmread\n",
    "from itertools import combinations\n",
    "from torch.nn.functional import gumbel_softmax\n",
    "from utils import gumbel_softmax_3d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-03T06:56:22.798543Z",
     "start_time": "2020-09-03T06:56:22.791808Z"
    }
   },
   "outputs": [],
   "source": [
    "# load data\n",
    "def load_graph(filename):\n",
    "    G = nx.Graph() # undirected graphs\n",
    "    for line in open(filename):\n",
    "        strlist = line.split(' ')\n",
    "        n1 = int(strlist[0])\n",
    "        n2 = int(strlist[1])\n",
    "#         weight = float(strlist[w_index])\n",
    "#         G.add_weighted_edges_from([(n1, n2, weight)])\n",
    "        G.add_edges_from([(n1, n2)])\n",
    "    return G"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-03T06:56:23.181464Z",
     "start_time": "2020-09-03T06:56:23.175455Z"
    }
   },
   "outputs": [],
   "source": [
    "# load data\n",
    "def load_graph2(filename):\n",
    "    G = nx.Graph() # undirected graphs\n",
    "    for line in open(filename):\n",
    "        strlist = line.split(',')\n",
    "        n1 = int(strlist[0])\n",
    "        n2 = int(strlist[1])\n",
    "#         weight = float(strlist[w_index])\n",
    "#         G.add_weighted_edges_from([(n1, n2, weight)])\n",
    "        G.add_edges_from([(n1, n2)])\n",
    "    return G"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-25T10:29:52.897481Z",
     "start_time": "2020-08-25T10:29:52.779971Z"
    }
   },
   "outputs": [],
   "source": [
    "# Jazz\n",
    "# load data\n",
    "# print('\\nJazz\\n')\n",
    "data = mmread('./data/jazz.mtx')\n",
    "F = nx.from_scipy_sparse_matrix(data)\n",
    "G = nx.Graph()\n",
    "for edge in F.edges():\n",
    "    G.add_edges_from([edge])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "G = load_graph('./data/bio-celegans.edges')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-25T10:37:17.637381Z",
     "start_time": "2020-08-25T10:37:17.607829Z"
    }
   },
   "outputs": [],
   "source": [
    "G = load_graph('./data/email-univ.edges')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-03T06:56:25.580730Z",
     "start_time": "2020-09-03T06:56:25.332400Z"
    }
   },
   "outputs": [],
   "source": [
    "G = load_graph2('./data/fb-pages-government.edges')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-25T10:32:07.080240Z",
     "start_time": "2020-08-25T10:32:07.074980Z"
    }
   },
   "outputs": [],
   "source": [
    "G = nx.karate_club_graph()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-17T08:39:44.379087Z",
     "start_time": "2020-08-17T08:39:44.098548Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWQAAADuCAYAAAAOR30qAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzsnXdYVEcXh99t9A6KXRQVFUUsscWGihVbYq+JJho11hR7iDX2TmLPZy/RBLso9hJrFEUFNfYuVUTKlvv9QVhZ2YVdmqj3fZ59gvfOzA7h7tmZM+f8jkQQBERERERE3j3Sdz0BEREREZEURIMsIiIikk8QDbKIiIhIPkE0yCIiIiL5BNEgi4iIiOQTRIMsIiIikk8QDbKIiIhIPkE0yCIiIiL5BNEgi4iIiOQT5KY0dnFxEdzc3HJpKiIiIiIfJhcuXIgQBKFAZu1MMshubm6cP38+67MSERER+QiRSCT3jGknuixERERE8gmiQRYRERHJJ4gGWURERCSfIBpkERERkXyCaJBFRERE8gmiQRYRERHJJ4gGWURERCSfIBpkERERkXyCSYkhIiIiHw4Rr5LYeuEhYU9f8jJRhZ2FnPKF7OhUvRjONubvenofJaJBFhH5yAh5EEPAkVscvfECgCSVRnvPQv6UecE3aORRgEENy1CluMO7muZHiWiQRUQ+ItadvsvUPWEkqtToKzif+J9x3n/tGcduRDCuVXl61nbL20l+xIgGWUTkIyHFGF8nQanJtK0gQIJSzdQ91wFEo5xHiAZZROQjIORBDJN3XObR7sUk3r2EJvEVcofCODbsjaV7DZ22MSc2EHtiAwW7TgE3b6buCcOrmANexUT3RW4jRlmIiHwEBBy5RWKyErmtC4W6T6f4iM04NOjJi+0zUMU807ZTRj/hdfhJZDZO2muJKjW/Hrn1Lqb90SEaZBGRD5yIV0kcvfECicICh/o9kDu4IpFIsSpTE7m9K0lP3xjbqANLcGz0BUjfbJ4FAQ6HvyDyVdI7mP3HhWiQRUQ+cLZeeKj3ujo+GmXUI8wKlAAgPuwEEqkcS/dP0rWVAFv/0T+OSM4hGmQRkQ+csKcvdULbAAS1iogds7Gp3ASFc3E0yQnEHF2NY9Ov9Y6RqNIQ9iQuL6b7USMaZBGRD5yXiSqdfwuChohdc0Amx8n3GwBijq/H2rMxCodCGYyjzNV5iohRFiIiHzx2Fmn9wQKRexaijo+hYKefkchS7iXeC0EdF0ncxd0AaF6/JCJwOna1O2Jfu+N/4yjyfvIfGaJBFhH5wClfyA5z+VOSVBqiggJQRj7AtesUpIo36dGu3aaCWq3995PVI3Bs8hWWpasDYCGXUr6wbZ7P/WNDNMgiIh84HasXY17wDVSxz3l1aR/IFDxc1Et736nFYGw8fXQ7SaRILWyQmlkCIAAdqxXLw1l/nIgG+T1DFIQRMRUXG3MalivAgesaSo7eZVSfYoNWaX+WAD4eBcTnKw8QDfJ7gigII5IdBjcqw/GbESQo1Zk3fguNMgmruydQq6sik8lyYXYiqUgEfQojBqhRo4Zw/vz5XJyOiD4yE4RJRSIBC7lMFIQR0YspWhapWCqkDKxdiL9mjUSlUrFmzRpKlSplsL24g9OPRCK5IAhCjczaiSvkfI4oCCOSU6Q+D5N2XiVZpQGp4ajXt7/cv21xkHnz5lGzZk1mzZpFnz59kEgk2vbiDi5nEFfI+ZiQBzF0XX6aZ6cDib9ykOQXd7Gu0BAXvxEACGolETtmkfTkFuqXz3HtNg2Lkl4AWCpkbO5fWxSEEUlHk059kXu15G6yDRLeSG5CSjSFQIrPeFCjMumen8uXL9OzZ0/Kli3L0qVLcXFxEXdwRiCukD8AAo7cIlGlRm7jjH3dLiTc+QdBmazTxryYJ7Y12hEROF3neqogzJKemT4DIh8RN2/e5PKRndxbvZgEjYyt/zxk9vKNeNesQ7GCzpQvbEvHaobdC15eXpw9e5bx48dTpUoVek1axvZ7UnEHl0OIBjmfkioIIwhg5VEXgKSnt1ArI7RtJDIFdp+0S/nHW9vPtIIwH7PvTkSXhQsX0r9/f6ysrLACBjRwZ8mwbYwZ0Ypq1byNGsPCwoLZs2dToV4LJh6NJOrQSr2SnqqYZzxa0g+JwkLb16725/BpN1HS0wCiQc6nGBKEMYVUQZgBDdyzPyGR956YmBjWrVtHaGioznWZTIZGY/xBXypn4hyQSGO1kp4y+wIk/HueF9tnUKTvYm274iM2I5HqRmeIOzj9iFoW+RR9gjCmIgrCiKRl5cqVtGrViqJFi+pcl0qlJhtkraSnWeaSnvoQJT31I66Q8ylvC8JkfRxREEYEVCoVixYtYsuWLenuZcUgGyvpCfDo1y9BIsHCrSqOPl8is7IHxB2cPsQVcj4lrSBM9sYRBWFEIDAwkKJFi1KzZs1097JikI2R9JRa2VGozzyKDvqdwl/MR0h+TcTO2dr24g4uPaJBzqekCMKk/HkEjRpBlQwaNQgaBFUygiYl40pQKVPuAYJGlXLvv9gjURBGJJX58+czYsQIvfekUilqtWkZfMZIekrNLDEvXBaJVIbM2hEn34Ek3rmIJul1mnHEHVxaRJdFPiVVEAYg9uQmYk9u1N6Lv3oY+0+74VC/B4+WDUD98jkAzzf/BEDRb1Yid3AVBWFEADh37hwPHjygffv2eu9n5VDPGEnPdEi0HdKMI+7g0iIa5HzKG0GYZzjU74FD/R5626UVgUmLRCIKwoiksGDBAoYMGYJcrv/jnhWXhTGSnkmPw5GaWyN3KoIm8RVRB5ZhXqIyUgtrQNzB6UM0yPmY7AjCWMhlDGpUJhdmJfI+8fjxY3bv3s2iRYsMtsmKQTZG0lMikRJ9dA2a1zFIzaywcPOmQNsftW3EHVx6RIOcj6lS3IFxrcpnSRBmXKvyYtC9CAEBAfTo0QNHR0eDbbJikLU7uGsZS3paV2yo97q4g9OPaJDzOanppcZoBYCApUL+UWoFiKTn9evXLFu2jFOnTmXYLisGGaBHVRf2X3kAMjOT+4o7OP2IBvk9oGdtN7yKOfDrkVscDn+hVxBGrdGgvBfC+ikDqObmkivzEKUV3y/Wr19P7dq1KVu2bIbtshJlcf/+fb7p1JIa7QdwVeEh7uByCNEgvyd4FXNgSc8aRL5KYus/Dwl7EsfLRCV2FgqtIEzndnO5fKQo1b74IkffW5RWfP8QBIH58+ezcOHCTNuaGmVx/fp1mjdvzvDhwxk5crio9paDiAb5PcPZxtxgZtOECRPo378/vXr1yrHKDpl92FJX6vuvPePYjQjxw5ZPCA4ORiqV0rhx40zbmuKyOHPmDO3atWPmzJn07t0bMG4Hl5Gkp8gbRIP8AdGwYUNcXV3ZvHkz3bt3z/Z4ojj++8u8efMYPny4joi8IYw1yEFBQfTs2ZPff/8dPz8/nXuGdnAHdm+nT/f29G9aWXRrGYFokD8gJBIJ48ePZ+TIkXTt2hVpBhUhMiPkQQxT94Tx7PR2veL4SY/CiDm+juSnt0AixaJEZRx9B5Bg4yRKK75jwsLCuHDhAtu2bTOqvTEGedOmTQwbNoy//vqLevXqGWz39g6u+YbxeCnq4GwjqroZg5g6/YHRrFkzrK2t+fPPP7M1ztvi+DZevjr3NYmvsPFuQdGBqyg6aBUSM0sid88H3kgrirwbFi5cyIABA7C0tDSqfWaHeosXL+b7778nODg4Q2OsD09PT65evWpSn48Z0SB/YEgkEiZMmMCUKVMwpTxXWt4Wx7cqVweppZ1OG0v3GliXr4fU3AqpwgLb6n4kPUpxV4jSiu+OqKgoNm7cyMCBA43uY2iFLAgC/v7+LFiwgOPHj1O5cmWT5+Pp6cm1a9dM7vexIhrkDxA/Pz8kEgk7d+7MUv+siOMnPbiKwuWN5GKqtKJI3rJixQratGlD4cKFje6jL8pCrVYzePBgdu7cycmTJzOsNJ0RFStWFFfIJiAa5A+QVF/y5MmTs7RKNlUcP/n5HWJPbsTR50vtNVFaMe9RKpUsWrSIYcOGmdTv7RVyUlIS3bp1IywsjCNHjlCwYMEsz6lixYpcv349S4knHyOiQf5A6dChAwkJCQQFBZnc1xRxfGX0Y55v8cexaX8sild6axxRWjEv+fPPPylVqhTVq1c3qV9agxwXF4efnx9qtZo9e/ZgZ2eXSe+Msbe3x9HRkXv37mVrnI8F0SB/oEilUsaNG5elVbKx4viq2Oc82zge+0+7YlMpfbyrKK2Yt2SkeZwRqQb5xYsXNG7cmFKlSrFlyxYsLCwy72wEFStWFP3IRiIa5A+Yzp07ExERweHDh03qZ4w4viougmcbx2JbvTW2VVulG0OUVsxbTp8+zdOnT2nbtq3JfaVSKc+ePaN+/fo0a9aMpUuX5lhiEYiRFqYgxiF/wMhkMsaOHcuUKVOMythKxRhxfCQSVDFPiT2xkdgTb+6X+G4rIEor5jULFixg6NChWTKkL1++ZPr06fz0008MHz48x+fm6enJsWPHcnzcDxGJKdvZGjVqCOfPn8/F6YjkNEqlEg8PD9auXcunn35qdL/+a89z4PqzTNTl9CORQPOKrmKJ9zziwYMHVKlShTt37mBvb29S37///psmTZrQtWtXVq3SX+wgu5w+fZpvv/2Wj9l2SCSSC4IgZPqBEF0WHzgKhYIxY8YwefJkk/oNblQGC3nWtq2itGLeEhAQQK9evUw2xvv27aNt27Y0atRIb/HTnKJChQqEhYWJkRZGIBrkj4A+ffpw7do1zp49a3SfVHF8S4Vpj4gorZi3xMfHs2LFCoYOHWpSvw0bNtCnTx+2b9+Om5tbrhpLMdLCeESD/BFgZmbGqFGjmDJlikn9etZ2Y1yrClgqZGSqUaPRYKGQMq5VBVFYKA9Zu3Yt9erVw91dvwKgPhYuXMioUaM4ePAgdevWzbJAvSmIB3vGIRrkj4R+/fpx/vx5Ll26ZFK/nrXd2Ny/Ns0rumIul2Ih131kLORSzOVSrGJu0cnpkWiM8xCNRsOCBQuMPogTBIEJEyawePFijh8/TqVKKXHjWRGoNxUxY884xCiLjwQLCwu+//57pkyZwtatW03qq09aceO2QDq3b4NnMQc6VivGo9tF8fX1ZWSfzzOs3yaScwQFBWFubk7Dhvrr1qUlNRX6/PnznDhxQif7zlSB+qwgRloYh2iQc5n8VPZowIABzJgxg6tXr+Lp6Wly/7TSiptHtGLUvK8pWrRoyj0vL9q3b8+kSZOYN29ejs5bRD/z5883SvM4KSmJHj16EB0dzeHDh7G11Y0PzyuXxW+//Zar7/EhIBrkXCI/lj2ytrZmxIgRTJ06lQ0bNmRrLEdHR6Kjo7UGGWDy5Ml4enoyYMAAypcvn93pimTA1atXCQkJYceOHRm2i4uLo3379jg5ObFnzx7MzdMvAvLCIKfVtMiOTveHjvh/JhdYd/ouXZef5sD1ZySpNOmEehL/u7b/2jO6Lj/NutN382xugwcP5sCBA9y4cSNb4zg5OREdHa1zrWDBgowePZrvvvsuW2OLZM7ChQsZOHCgXgObyvPnz/Hx8aFs2bJs2rTJYNu8MMh2dnY4OTmJkRaZIBrkHOZN2aOMCz6CbtmjvDLKtra2DBkyhGnTpmVrHEdHR6KiotJdHzJkCDdv3mTfvn3ZGl/EMJGRkWzZsoVvvvnGYJu7d+9Sr149WrVqxW+//ZZhBl9eHOqBGGlhDKJBzkFSyx6ZUhIdIEGpYeqeMC4/jMmlmekydOhQdu7cye3bt7M8hr4VMqSE2M2ZM4cRI0agVIpqb7nB0qVLad++Pa6urnrvh4aGUr9+fb799lsmTZqUqY85Lw71QDTIxiAa5BwkteyRIZRRj7g3qwMRO2enu5eXZY8cHBwYOHAg06dPz/IYhlbIkCKQX7x4cfEQJxdITk4mICDAYKjbqVOnaNKkCTNmzMg0WSTiVRJLjv7LSU1ZghJKMXzzRZYc/TfXKr2IoW+ZIx7q5RBpyx4ZImr/EswLl9V7L23Zo7yIvhg+fDjlypVj/PjxlChRIvMOb2FohQwpAvnz5s3Dx8eHHj164OzsnN3pivzH1q1b8fDwoEqVKunu7dmzhz59+rB27VpatGhhcIx0B86CCwjw4NLjXD1wFiMtMkdcIecQmZU9ir92FKmFNRYl03+QUsnLskcuLi589dVXzJo1K0v9M1ohQ8qHr3Pnzvj7+2d1iiJvIQgC8+bN07s6XrduHX379mXnzp0ZGuN3eeAsVg/JHNEg5xAZlT3SJL0m5vh6HBv3y3CMvC579N1337F+/XqePHlict+MVsipTJw4kc2bN4vb1Bzi77//Jjo6mtatW+tcnz9/PmPHjuXQoUPUrl3bYP93feCcGmlx927OjPchIroscoiMyh7FHFuLTZVmyO0KGDFO3h2Eubq60rt3b2bPns2cOXNM6pvZChnA2dmZ8ePHM2LECIKCgjI9XBJJwVAy0b5ff9XRPBYEgXHjxvHnn39y4sSJDF1PIQ9imLzjMo92Lybx7iU0ia+QOxTGsWFvLN1r8OrqYaL2BbzpIAgIqiQKfTGfqXskeBVzyBHBqNSDvdKlS2d7rA8R0SDnEIbKHiU/u03ivRAKf7nAyHHytuzRDz/8gJeXF6NHj6ZAgcy/MFIxZoUMMGjQIJYsWcLu3bvx8/PLzlQ/eDJKJjKTPSGpxOc42xYm5EEMlYrYMnDgQC5evMjx48cz/dsFHLlFYrISua0LhbpPR2ZfgIR/z/Ni+wyK9F2MjacPNp4+2vavLgcTe2oTZq7u2gPnnNC39vT05Nq1a7Rp0ybbY32IiAY5h0gpe/Q0vU/u/hVUsc94+GtKRWYhOREEDU8ihqUz0u+i7FHRokXp0qULc+fO5ZdffjG6nzErZEjRY547dy7Dhg2jWbNmmJmZZWe6Hywp7oQwElX63QnJagGJ3IxDNyM5eedvCj48jvmDOxw6dChdKvTbpB44SxQWONTvob1uVaYmcntXkp7eQu6gG0L3KvQg1pUaI5FIcvTA2dPTkyNHjmRrjA8Z0YecQ3Ssrr9ckY13c4oOWEGRLxdR5MtF2FZtiaV7DQp2mZSu7bsqezRq1CiWLVtmlIFNxdgVMkDLli0pU6YMixcvzuoUP2hM9e0mKjU8LFCL7v6/ZWqMwfCBszo+GmXUI8wK6Lo6VLHPSXpwFes0hWtz6sBZDH3LGNEg5xAuNuY0LFcgnW6wVGGBzMZR+5IoLJDIzZBZvVXdQaOhSkF5ngsOAZQsWZL27duzYIFxbhVIiWWOiYkx+sQ8dQX+4sWLrE7zgyRtMlHEztk8XNSL+3M78Whpf+JCggAQ1Epe/DWNh7/25d50PxLvXUYjlTNz/y2jkon0HTgLahURO2ZjU7kJCufiOvdehR7EvFhFFA6FtNdy6sC5YsWKYvWQDBANcg5iTNkjh/o9cGnzfbrrCpmEE0snMHToUF6+fJlbUzTImDFjCAgIIDY21qj2crkca2tr4uKM+5CWL1+eHj16MGHChOxM84MjbTKRXe1OFB24ihIj/6BgxwnEHFtL0tOUZCHzYp64tPkOmfUbaVNjk4nePnAWBA0Ru+aATI6Tb/r06/jQQ9hUbqJnnOwfONvZ2eHs7CxGWhhANMg5SJXiDoxp6YFUYzjiQh+WCin+bSsRemwPr1+/xtPTk8DAwFyapX7KlClDy5YtTXIrGOtHTsXf35+//vqLy5cvZ2WKHxxvJxOZFSiJRJ56qCtBggRV9BMkMgV2n7TDorgnpFFKS+vbzYi0B86CIBC5ZyHq+BgKdBiLRKZ7jJT48BrqV1FYeaQviJtTB86i28IwokHOYa5tX4rdv8FYKKSZlj2SSMBSIdOWPXJycmLFihWsW7eO0aNH06FDBx4+zJtEEYBx48axYMECXr16ZVR7U/zIkGLA/f39GT58OKZUO/9Q0efbjQz6lfuzP+fx8m+Q2Thh6Z5xZIMxvt2UA+eUj3pUUADKyAcU7PgTUkV691j8lYNYlauL1NxK53pOHjiLmhaGEQ1yDrJ8+XK2bdtG8BJ/tvSvk2nZo+YVXdncv3a6skcNGzYkJCSEKlWqULVqVRYvXpwnalzly5fHx8fH6PRWU1fIAP379+f58+d5vgPIj+jz7To3H0TxkVtw7TEDy3J1kMgyXpUa49tNPXBWxT7n1aV9JD+7neKrntOR+3M68urqYQAEVTLxYSew1uOu0JBzB86poW8i6RHD3nKI/fv3M2HCBI4fP46LiwsukK7s0c17D3lw+waDurejY7WMK4aYm5vz888/07VrVwYMGMC6detYtmwZXl5eufp7jB8/nmbNmjF48GCsrKwybGvqChlSfM/z5s3jm2++oVWrVhnq+X7oGEomkkhlWBT3JP7qYeIu7sGuRttMxsnYt5t64HzguoaSo3cZbCeRm1FixOb0NwQNyXcusjcwku7du2dbYN7T05OAgIDMG36EiCvkHCA0NJSePXvyxx9/ULasrnhQatmjeV288fdxRX5uPQMauBsdTVG+fHkOHz7M119/TdOmTRk9ejSvX7/OjV8DgMqVK1O7dm2WL1+eadusrJABfH198fT0NCmq40NDqVSSEBuZcSONBlV05mntxvh2BzYojcTEs41ULM0UTOxSj8WLF1O9enUOHDiQpXFSqVChghhpYQDRIGeTJ0+e4Ofnx/z586lfv36GbQsVKsSzZ89Mfg+pVEq/fv24cuUK9+/fp3Llyuzfvz+rU86U8ePHM2vWLBITEzNsl5UVcipz5sxh5syZWfr/8b4SGRnJ+vXr6datG66uroQc3YuMFKOkjo8h/tpRNMkJCBo1CbcvEH/9qFaMSlApEVTJKT9rVAiqZARBMMq3m5SUxPQfB+J451A691lmWCqkjGtVnj5tGvH3338zbtw4Bg0aRLNmzUyuYJ5KaqTFnTt3stT/Q0Y0yNkgPj6eNm3a8NVXX9G9e/dM2xcsWJDnz59neWXg6urKhg0bCAgIYMCAAfTo0YPnz59naayMqF69OlWqVOF///tfhu2yukIGKFu2LF988QXjxo3LUv/3AUEQCA0NZfr06dSrV4/SpUvzxx9/0KRJE0JDQzm2eiZy+X9eQ4mEuIt7eRjwBQ/mdyX68Cocm3yNVbkUsaBHywZwf/ZnqOMieb75p5SfY59nmkz06tUr/Pz8UCqVnFw9g/GtK2CpkJl84JxyTULHjh25du0a7dq1o0WLFvTq1StLZZlEP7J+JKacdteoUUM4f/58Lk7n/UGtVvP55ykl71etWmW0cI6joyO3bt3KtkZwfHw8EydOZPXq1fzyyy98+eWXOSrec/r0abp27crNmzdRKPRviZctW8a5c+eMcm/oIzY2Fg8PD/bu3UvVqlWzM918Q2JiIkeOHGHXrl3s2pXir23Tpg1+fn40bNgQCwsLnfb9157nwPVnmWbo6UMigeYVXQ1qTERERNCqVSu8vLxYsmSJ1vhffhjDr0ducTj8BRJSDgZTsZBLEQAfjwIMalQmQ0Ghly9fMnv2bAICAujbty9jx47F0dHRYHvtvF4l8cXE30iydKG4u8c7rcSeV0gkkguCIGQqBiIaZD0YUttK+8CMGDGCkJAQ9u3bZ5I+Q4UKFdi6dSuenp45MtdLly7Rv39/rKysWLp0KR4eHjkyLqT4ert160bfvn313t+6dSsbN25k27ZtWX6PZcuWsW7dOo4ePfreqsE9fvyY3bt3s2vXLo4cOYKXlxd+fn74+flRsWLFDH+vkAcxdF1+mgSl6VE0lgoZm/vX1ms079+/T/PmzWnfvj3Tpk3TO4c3B84v2bA1kK6ftaViUYdMD5zf5smTJ/z888/8+eefjBo1im+//TbdFw/oiiep1SpUwpsNeuoXQV5XYs8rRIOcBTJS20r7wLg8/4c/l8/j1KlTRq0I0tKoUSN++uknGjdunHljI1Gr1QQEBDBp0iSGDh3KqFGjciR64dixY/Tt25ewsLA3W+s0HDx4kKlTp3Lo0KEsv4daraZ69eqMGzeOTp06ZWe6eYZGo+HChQvaVfCdO3do0aIFrVu3pkWLFibvft5oWRjvykrx7VZIFzIJcP36dVq0aMGwYcMYOXKkUeM5Ojpy+/Ztk5/nt993zJgxXLx4kSlTptCjRw9tREZm4kmpSCRgIZcxrlV5vb/b+4qxBlkMe/uPzB6Y1G3d/qtP0ahcGDFrXZYe3qwe7GWETCZj6NChdOjQgSFDhuDt7c2yZcsyPWTMjAYNGlC0aFE2bdpEz5490913cnLKsg85FZlMxvz58/niiy/w8/MjXi3NdHfyLoiLi+PAgQPs2rWLPXv24OTkhJ+fH/PmzaNu3bp6v7CMJdXwGGOwBI0Gc7lhY3z27Fnatm3LzJkz6d27t9FzsLGxIS4uLlsGuUKFCgQGBnL8+HF++OEH5s6dy4wZM3huV87oL5y0wvjAB2WUjUFcIZPzK5SMGDZsGG5ubowYMcLEWRrPX3/9xZAhQ2jZsiUzZ87M1ocsODiYIUOGEBoamq6U/N27d2nYsGGWDnXepkX3ASSUbsBTiRNgeHeSl9vZf//9V+uK+Pvvv6lbty6tW7emdevWuLu75/j7ZebbVQsCMddOYH33JLfOHkz3JXDgwAG6d+/OqlWrTNYbrlChAtu2baNixYo58asgCAJ//vknP84IQNNoKBoBIvf/qlccPzniPpG75mpD/MwKlcHRdwD2hUsZdMm8b4grZCNJq7b1NvHXjhJzciPqly+QWTvi3Ho4FsUrAZCg1DB1T5jJlRRyY4X8Nh06dKBx48aMGzcOT09P5s6dS5cuXbLko23SpAn29vZs27aNzp0769zLiRUypHwh3nFvR2KyGok0/d9Buzu59oxjNyJybTurVCo5deoUu3btYvfu3URFRdG6dWsGDhzItm3bjJK6zA5exRzSJRO9TFRiZ6GgfGFbOlYrhm+D8dy8eZPly5czcOBAbd8tW7YwZMgQ/vrrL+rVq2fye9vY2BidMm8MEomEzz//nH3xJVIOLZOTDIrjy22cKNB+DDL7giBoiPtnNxHbZ2L+1eIcE8Z/X/joDXJata20JNy5SPSR/1Gg3SjMipRD/Sq94clKJQX+s59vAAAgAElEQVRXV1fCw8OzNWdjsLe3Z/HixfTs2ZP+/fuzevVqfv31V0qVKmXSOBKJhAkTJjBmzBg6duyok6Vla2tLQkICSqXSYCRGZqTuTpJUApJMMsByYzsbGRnJvn372LVrF0FBQZQqVQo/Pz9Wr15N9erVs52VlhVSk4n0sXTpUmrVqsWECRPo3r079vb2/Pbbb0yZMoUDBw5kOZPT1tY2Rw0ypByOH7sZAUiQmhkWx7cu/ylSCxsg5W8skUhRRT/J80rs+YGP2iC/rbaVltgT67H/tBvmRcsDILd1SdcmKw+Mq6trniZD1K5dmwsXLjB37lw++eQTRo0axYgRI0zyebZq1YqffvqJHTt20L59e+11iUSCo6Mj0dHRFCxY0OS5GdqdROycTeLdEDTKRGTWjtjV/hzbKs2197O6O4GUrfTVq1e1B3KXL1+mcePG+Pn5MWfOHIoUKWLy75GXfPLJJ3h4eBAZGcnUqVOxsbFhzZo1HD9+PFt16lJ9yDlJRpXY9Ynj35/XBSE5AQQB+/+Md6p4kqEvqA+Nj9ogG3pgBI2apCe3sCxTi0dLvkZQJ2NVtjYOPn3TKWSZ8sBEvEri71gbbhWoR9/V5/LswEqhUDBq1Cg6duzIwIED2bBhA8uWLeOTTz4xqr9EImH8+PFMnjyZdu3a6bg+smOQDe1O7Gp3wrnlMCRyBcrIBzzdMAYzV3fMC5XRtjFld6IvNtjPz4/x48fTqFEjvSFa+ZlFixbRrFkzFixYQOnSpTlx4gSFChXKvGMG5LTLAgxXYjckjl9ixGY0yYnEhx5EZpfyPOV1JfZ3zUedqWfogVHHx4BGxevwk7j2nEHhLxeS/Ow2safSC68Y88CEPIih/9rzfDrjEFuuxaMs6s2hsOcEXnrM/OAb1J1xiAHrzhPyIPPqD9nB3d2doKAgvv/+e9q0acOwYcOMXhW1a9eO5ORk9u7dq3M9q37kjHYnhnSB05KZFvDjx49ZsWIF7du3x9XVlalTp1K8eHF2797NnTt3WLx4MS1atHjvjDGkRL9YWloikUioUKFCto0x5I7LQp94Umbi+FIzC2yqtiRy19yUzyF5W4n9XfNRG2SDalv/rYJtq7dBbuOEzMoe20/ak/Cv/giTmNfJBt9j3em7dF1+mgPXn5Gk0pCs1rVAiSoNSSoN+689o+vy06w7fTdrv4yRSCQSevTowdWrV4mLi8PT05MdO3Zk2k8qlWpXyWkjc1JXyKaS0XYWjNMFTqsFrNFoOHfuHP7+/lSvXp1KlSpx8OBBOnXqxO3btzl+/DijRo3C09PzvU1AgZQMzbZt21KhQgWUSiVnQq4xZs1Bhm++SN/V5xi++SJLjv6bqWj92+SGy+LtSuyZieOnaYigSkIdF/nfOHlbif1d8lG7LN5+YFKRWdgg0+MzNsSewD8oP6M3Hh4elC9fHg8PDzw8PLiS6MiCo/fyZfyls7Mzq1at4siRIwwYMIDVq1ezcOFCihYtarBPx44d8ff35+DBgzRt2hTI+grZ0O5EO7/mg3DyHUDSozAS71/RqwucqNJw4OxVzq6exu7du3M0Njg/khr1Ub58eaYuWUf7Mb8iK+7FxtA4kL0RgrKQP2Ve8A2TwgRzw2XxdiX2VHF8165TdFx/CXcuIrO0Q1HQDUGZRMyxtUgtbFC4FH8nldjfJR/WE2sCDx8+5GnYBVC5gDz9h92mclPiLuzCsnR1kMmJO78dqzLpfa4Wcik/DPuKRq5fEBYWRnh4OEeOHGHxhp1Eevci7vJ+4q8cJPnFXawrNMTF7038ccLdS0TtX4L65QvMipTDpfUIEuwLZvnAKis0atSIkJAQpk2bhre3Nz///DPffPNNuphjSEniGDduHJMnT6Zp06ZEvEoismA11t+Wc8hEn7ih3UlajNEFvv7vPQZUqcLYsWNzJTY4v/Dw4UOaN2+eok3x2WB6rjqPzK0aKfsEXbISJmhra8vTp09zdM4dqxdjXvAN4I04PjIFDxf10rZxajEYiUxB1IGlqOMikMjNMCtcloKdJyKRm72zSuzvio8qMSQ+Pp7AwEBWr17N+fPnadOpO6dcWqJvASuoVUQFLyP+2lEkcgXW5evj6PMlErmuboW5XMqpUY3TGaBU0Zj4sFMgkZBw5x8EZbLWIKtfx/Jo6dc4txyKVZmaxBxbR+LDqxTuPSdT0Zjc4tq1awwYMACVSsWyZcuoXLlyujYqlQqPOs3w7v4joVECKpUSNW+Mt7FJHMM3XyTw0mOj5hW5ZyEShTlOvgPS3evgXZR5XbyN+wXfU8LDw2nevDmDBw+mcP1OuZLEtGTJEi5evMjSpUtzYMZvyE3xpPcJMTHkPzQaDceOHWPNmjX89ddf1KlTh759+7J9+3YsLS0NPjASmRzn5oNwbj7I4NgSSYoq1tvGOO2BlZVHXQCSnt5CrYzQtnl942/MXEpgXT4liN++XnfiFnZHGfkAhXNx9l15RO+vV+HlUVrrCilVqlSubsMrVqzI0aNHWblyJU2aNKFfv3789NNPWFpaattsOv8Qqe8ILjxTgkQK6K6kjV2dlS1gjVwioBJ0V3jq+BgS74VgWaYmErkZiXcvEX/9KC5tfkg3xsewnT1//jxt2rRh2rRpVGvaga7LT/M6Iclg1htA/PXjxJxYjzouErmtCw4NezMVSYa7rtxwWUBKJfbjNyOyJJ5kIZcxqFGZzBt+QHywBvnmzZusXbuWtWvXYmtrS58+fZg6dSqFCxfWaZcbD0xmB1YAyhf3UBR8k6QhNbNA7lCI5Bf3UTgXRyGXIy3zKY8enefgwYOEh4fz+PFjSpcureOrTv1vdtKj0yKVSvn6669p06YNw4cPp1KlSixZsgRfX19tEodSkOrbKetgyCceFRXFsmXLWLxiNYrPp4P0rUfwP13gyKBfQdAgty+oowus8x582NvZgwcP0q1bN5YvX067du3ov/Z8itaFRm0w6w2ZjIidcyj4+XgsSlcn4d/zRAROx6JYhQzDBHMjygJSKrGPa1U+i6v68h9E2rQp5KlBNkbWMjvExMSwefNm1qxZw61bt+jevTt//vkn3t7eBk/Wc+OByezACkhJerCy17kmNbdOCYwHlBqwLOzOnB+6abPFEhISuHXrltZXHRwcTEBAAGFhYVhZWWkPE9Maazc3tyytqgsVKsSmTZvYu3cv/fv3p4pPW8KKttDRVzCG1CQOB81L9qxbwsaNG2nXrh3b1v+PX45HcClC899KOwWZlT2FekzPdFxBo6GUeSJO1sZLnxoit5/LrLB161YGDRrEH3/8QcOGDXV2XRllvcntXJBaWGtXy1ZlPkGiMEcZ/YTD4U4Gk5hyI8oilZ613UhKTmbSzlCkcjOEDL7NP1S1N2PJE4Ocsayl6SfCaVGpVAQFBbFmzRqCgoLw9fVl9OjRtGjRwuh0XlPUtox5YIw5sJIqLNAk6dbG0yS/RmL2xj2wc18wK79qQMGCBSlUqFC6V/v27SlUqBCurq4APHjwgPDwcMLDwzlw4ADh4eE8ffrU4KrawSHz/9ctW7YkNDQU30l/kJCsSpferE6II3LPAhLvXkRqaYdjwz5YezbSaZOQrOSbhX/RsZAZ48aN48SJE/j6+lK+bnPkVXuTlUpvFgopTw7+D98jv7F06dIsHejl5nOZHZYtW8bPP/9MUFCQVrjf2Kw3uWMRFM7FeX3zDJbuNUi4dRaJXIGiQKkMk5hyy2WRyp39a/COeEmEazWe4IyZQq7z5S4VVEgkUnwrFs5UGP9DJtcNstGyliYKx4SEhLBmzRrWr19PqVKl6N27N7/99htOTk5ZmmfP2m54FXPIkUoKhsLp0qIoUJL4Kwe1/9YkJ6KKfqqTStqpnR8z/vcjz58/5+nTp9rXkydPuH79OocPH9a5JpPJdAy2n5+fVps3MTGR6OhoAgMDuX//Pjdu3MDa2trgqjptlEWCICfSzBWJntVx1P7fkMgUFBuyjuRnt3m+dSKKgqUwK1DyTSOJFHmJKqxdN4xmDevSqVMnVq5cibOzc7aU9rr+/Bfz58+nVq1ajB49muHDhxu9G8it5zI7CILAtGnTWLlyJceOHaNMmTfuMFOy3qwrNSZixywEVTISmQKX9qORmllkmMSUWy4LSFHNW7JkCf/88w916tRh6859XH5lpSOepIl+wMVtv7Hklz25Mof3hVw1yKZ82IyJw3327BkbNmxg9erVREVF0bt3b44ePZpjVTL0qW0dPnmaUkUL0aJOZaMrKaSNvxQ0akh9CZqUQpVSGVbl6hB9eBXxYSexKvMJsSc3oijopv1QpR5YmZmZUaxYMYoVy9hXKggCr1690hrntAb87deLFy9wdHTE0dGR+Ph4QkJCuHDhAq9evSIqKorY2FhKlChBhQoVqFy5Mi9cvNForNO9pyY5kdfhpyjyVQBSM0ssintiVaYW8VcPY9boC522CoWCyesPMMinnM51U3YnCAJSQc24VlW0/b7//ns6dOhA//792bRpEytWrMDbO+Ooi5x+LnMCjUbDyJEjOXToECdPnkx31mFs1lvC3UvEHP4d1+6/YFbIneSnt3ixdTLyzhMxcy1tMOstN1fI3333Hd9//z1hYWEUKVKEOtUqU+etNq9fl6PQjz2IjY3F3t5e7zgfA7lmkDOStcyIt4VjEhMT2bFjB2vWrOHEiRO0b9+euXPn0qhRo1xT4kqrtvXd2bUUksYxoEH7THq9IW38ZezJTcSe3Ki9F3/1MPafdsOhfg8KdBhL1P4lRO6ag1nhchRo+6O2nakHVhKJBFtbW2xtbSlbtmyGbdVqNREREQYN9uPHj7l//z6HDh1i7969uLT5DovyDdKNo4p6hEQqReH0JplEUbAUSfevpGur1MDN56/TXQfd3Unwtaeo1WqENId9qbuTBmWcORQwGvt6IwA37X13d3eCg4P5/fffadasGV999RUTJkzQiQ5JJeRBDN9PnEn0pQN6Y8PjQoJ4+fdW1PHRmBeriHOrYchtnbMlaJQZSqWSvn37cufOHY4ePar3gDajrLeCnX7WZr0lP7uNeXFPzAunPAPmhcthVsSDhLuXMHMtbTDrLbd8yEFBQYSGhrJ582b69u1Lnz599LazsrKiXr167N+//72pHJMb5JpBThWOeXlhp8HECI0ykehDq3gddgJBo8KsQCkK9ZxBokrN5G1ncbq2ja1bt1K1alV69+7Npk2bsLGxya0p66VYsWImlyt3sTGnYbkCHLj2DIf6PXQOYNJi6eZN0f5L0l03FE6XU8hkMlxdXXF1daVKlSoZtk1ISKDv/87y9/30qyeNMgGJuZXONam5FZr/Dibf5p+rYaxYcV67OndyctL+XLmoPUt61qD/kJG8KlAJx9KV+GvXPrp0aKvVAna2MedIyZ/o1asXDRo00FlJSSQS+vbtS8uWLRk6dChVqlRh+fLlNGzYUGcOAUduobFyxL5uF21seCqJ968Qc3QNrt2moXAqQlTwMiJ2zNIeMmZFbjUzXr9+TadOnZBIJOzfvx8rKyu97YzNejMvXJaXp7eS/Ow2Zq6lSX76L0kPrmJbrVWGYYKpK2RBEHIstTw5OZlhw4Yxf/58kpKS2L17NwsWLDDYvnXr1uzatUs0yDlN2hNhuY2z3ocfIGrfYgSNmiJf/4bUwobk5ymGTxDg3KPX9CpemosXL1KiRAl9b5MnFC9enGPHjpncr2kRNUGXk5DITTeq+SH+MiYmhpCQEC5dusTtOwqwLJmujVRhiZCka3yFpNdIzdKvTAGExFecOnWK6OhooqOjiYqK0v6cmJiIg4MDr169olSpUhQrVoxnhw6R5PSU+46O/H7WUWu8q1SpwldffcXs2bNxdHTE1tZWa0QKFy7MH3/8QWBgID169KB169bMnDkTe3t77XNpVU5/bHjCrbNYla+n9X/b1+3Ko4A+KKOfoHAsnOP6vNHR0fj5+eHu7s7KlSszPIT+vFpRZgeFARlnvdl4+mBfrxsv/voF9esYZJZ22NfphGWpahnuuszMzJBKpSQnJ+dIPUZIUaUrXbo0rVu35vfff8fHxwcXF8OSBK1bt2bixIloNBqDu9/8GBGTk+SKQU57ImwoMUIZ+ZDXN89QbPBqpP+tstLKK1qYm1OsQcd3aowhxSA/fJh5XHFajh8/zrfdPqfnxKXsfSLN1/GXgiBw//59Ll26pPN68eIFXl5eeHt7U9GtHlGxpMtolDsVRdCoUUY90rotkp/fQVEgvfGWqJUUthIYOHAg1apVS5eanZyczKNHj/D09GTJkiXEx8dz8OBBypcvT2xsLI8fP+bq1ataAx4UFMTRo0eJj48nOTkZBwcHrcFOfTVv3pxz585RsmTJlJqAFXzRaAw/8oIgoOvETvlZ+eIeCscUn25O6fM+fvyY5s2b4+vry+zZszN0v507d45Ro0ahKeaLpGhl5PYFKTl6l8H2dtXbYFddt4STMbuuVLdFThjkp0+f8ssvv3Dy5EkkEgmrV69m+PDhGfZxc3OjQIECnDt3jlq1auncy68RMTlNrhhkY+Jwkx6HI7cvSMzx9cRfPYzMxhH7T7tjXf5TIP/ooBYvXpwHDx4Y3X7Pnj306dOHDRs24OvrS7V8VG03OTmZ69evpzO+lpaWeHt74+3tTbdu3ZgxYwbu7u5aoxnxKolPZxwCje7fVGpmgZVHHWKOr8e55VCSn9/m9a0zFOo5K917y+RyHKPD+eKL+Tx9+hQfHx98fX1p2rQp7u7umJmZcf/+fSpXrqx1M1haWtK3b1+9bqrt27fzww8/cO/ePWQymdZQv/1yc3Pj8uXLrF27FrvmDsjc3z5OeoOlew0its/EtmpL5I5FiD25CZAgqN4op+XEc3nz5k2aN2/O119/zejRow26CG7cuMG4ceM4deoU/v7+1Gj2OT1Wncu1rLfUSIuMVrHGMmbMGPr27YuHhwd37tzh2rVrtG7dOtN+fn5+7N69W8cg58eImNwiVwyyMXG46rhIlC/uYVWuLsW+XU3SozCe/zERM5cSKFyK/zfOu9dBdXV1JSoqiqSkpExXDps3b2bo0KHs2LGDOnVSPvg5GU5nCrGxsYSEhHDx4kWt4Q0PD8fNzU1rfFu2bEmVKlW0ccyG0PrE9aSYOzUbROSeBTxc1AOppR3OzQbphryRksRRVB7LrCn+2C6YzaNHjzh48CDBwcH8/PPPWFpa0rRpU169eqWNu4UUg5yQkKDXILdr147169czadIkfvnlF61P3BAJCQk0mbSVjNQzLN28cajXnRd/TUOT9Bq7T9ohMbdEZuus0y47z+XFixe1W/Ovv/5ab5vHjx8zceJE/vzzT7777jtWr16t9S1nJYlJqlEyrpVnps9WTkVanDlzhqCgIMLCUlwsa9eupUuXLpiZZZ7E07p1a0aMGMGkSZOA/BkRk5vkikE2Jg5XIjcDqRz7T7umqHqVqIxFicok3PlHa5DjIp/z4sULChQokBvTNIroBBWFG/di8LqzaOQWBn1WS5cuZdKkSXrrmhlTvDKr/i9BEHjw4EG6Ve/z58+1Loc6deowcOBAKlWqZPDQKDMMpZjLLG0p+Pn4DPtKNEr+3fkrpZeNYOzYsQwcOJDevXvTu3dvBEHg2rVrHDhwgOnTpxMbG8u5c+fw9fVFKpUSHR1t8O+/aNEivLy86Ny5s44h14elpSU1vStlKmhkW90P2+p+ACijHhF7ajOKAm46bbKqz3vkyBE6d+7MkiVL+Oyzz9Ldj4mJYebMmSxdupS+ffsSHh6eLq7elDBBQaPB0lxOwsmtuLVxIW1kij5yItJCo9EwZMgQpk+fjp2dHYIgsGbNGjZu3Jh5Z6Bu3brcuXOHx48f80JtxdQ9YTw7vV1vYIAq5hmPlvRDonhTZMCu9ufwabc8VUzMSXLFIL99IqwPRUG3DMeQoebfCycpM7E7Li4u1KxZk1q1alGzZk2qVq2qN6QpJ0nrs5J4tSH41kvgJZDeZ7V3/RKWLVvG0aNHdYL53yaj4pXGoFQq9bocLCwstKverl27Mn36dB2XQ06QnRTzUa2r8NS5LTNmzGD58uXMmTMHf39/vvjiCxQKBZ6enlSsWJFp06YRGhrK48ePCQ4OJi4ujqpVq1K3bl2aNm2Kr68v3t7eWn+rq6srM2bMoF+/fpw9ezbTpJDU5zIxWak3NhyNGmX0YxQuJVG/fEHk3kXY1miLzOLNCj2rgkaBgYHaWOnGjRvr3EtMTGTx4sXMnDmTNm3acOnSJYoXL25gJON2XRpBICb8NP19y1OqXytGjhzJ6dOnM/RV58QKefXq1chkshSfPXDq1CnMzMyoUcO4yBS5XE6zZs3Ys2cPZ829SVSpMwwMACg+YjMS6dsiVzkfEZMX5IpBThuHaygxwqJ4JeR2BYj9ewv2dTqT9DicxAehODbumzIxuYL9SyfhaPULYWFhnD17ljNnzrB27VquX79OxYoVtUa6Vq1alCtXLsfiktP5rN4SR0/rswoOfYzs8k2OHz+eobi7qaS6HNIa3rCwMB2Xw+jRo41yOeQUPWu7IQgw4a+LSGSKDDUJQEBQJfOtT1m+qOcO9UbTtWtXhgwZwpUrV/jtt9+YNWsWkyZNonPnzty+fRszMzPc3d1xd3enfv36BAYGsnjxYqKioggODqZ79+5ERETQpEkTrYFO9dfPmTOHUaNGZTj/1OfSUGy43SftiNgxG1XMEyRmlthUbopD/Z46YyQlJ1NC9Rgw/ot15cqVjB8/nr1791K9enXtdbVazZo1a/D396datWocOXKEihUrGjWmMbuuPl1/ZdHElTx69IgFCxawYcMGraHUR3az9WJjYxk7diw7duzQfhZXr15N7969TQql8/PzY1Pgbm5WKJqhYmJGvK8Vq3NNDzlV1jL62Hqdhx/QJkYkv7hH5N6FKF/cRW5XEIcGvbDyqJupDmpCQgL//POP1kifOXOG6OhoPvnkEx0jnRVDlZVUXgu5lPGtM9abNYQxLofUV3ZcDjnFzp07GTUjgPoDphB87QkIAmqJrh6ySq1G9iwM36IaLh7czqFDh7T+d0EQ2L59O8OGDaNs2bJER0ejUqlo0qQJDx8+ZMuWLdqxateuzbx587T+eEjR6zh48CAHDhwgODgYW1tbatWqxc6dOzl48GCmhVuzpc8LlLV8zb+bp2JdqTHlPvHBzsUVO0uFXjeWIAjMnDmTJUuWEBQURLly5bTXd+zYwdixY3F2dmb69OnUrVvX9AllwsOHDylZsiTr1q2jRIkSdO3alfDwcIPPUK9evWjWrBm9evXSez8zvvvuO2JjY1mxYgWQ8jktWrQoly9fzjTTNC0RERFU/Hwojg166eyyo4+tRf0yIp3LQmbjBBIJFm5VcfT5UivaZSGXMsK3XL6oWG2sHnKuGeSQBzF0XX46SyfClgoZm/vXNsn/8/z5c86ePas10mfPnsXOzk7r5qhVqxbVq1fP0KAZmvPT9aNJehyu3RbJbJ0p2l9XyNuYOSuVSsLCwrRGN/XAzdzcXMfwent7U6ZMmRx1OeQEGo0Gb29vpkyZQtu2bWnfpSeF6rbHslAZndXZZ1WL0KpxA4YMGUJgYCBOTk4sX75cZ5UUHx/PpEmTWLVqFZ9//jlbtmzBzs6O//3vfzRq1AgAHx8fJkyYkG6Ln4ogCFy5coXg4GCWL1/OzZs3qVq1Kr6+vvj6+lK3bt10B7HZeS7N5VK8iztw6UEMarVaR8v5bWH+ykXt+PHHH9m3bx9BQUHa3dOJEycYNWoUL1++ZPr06bRq1SpXa/w1b96c0NBQHj58SJcuXfDy8mL8eP0+/4EDB1K5cmUGDTKsAW6I69ev06BBA65evaqtQL5582ZWrFjBgQMHTB6vwpfTSSikWyDhbYOsSU5AGfkQM9fSaBJeErX/NzTJCbh2maztk18KGLxzgfq81kEtWLAgfn5++PmlHMhoNBpu3bqlNc5btmwhNDSUcuXK6RjpChUqaA2fobL0AE7NvsG2SnOD7/+2zyo2NpbLly/rrHqvX79OyZIltUZ31KhRVKlSJUeqBucFmzZtwtramjZtUmJcr/5zhmn+Y/VusxcsWECXLl04f/48vr6+LF68mCFDhmjvJwhySrXqT+vSLTnyTwhmDb6mXEln+g0ahnuxlCrRqVEWhpBIJHh5eeHl5cWwYcOoW7cu9evXRyqVMmbMGK5du6bjf65cuTJVijswwqck0/ZcBxOSdhQyCWqNwNm7Uf+trnWNqNaNdfUZR2+8oPiLc8SHnOLYsWM4OTkRGhrK2LFjuXz5MpMmTaJHjx558oWbqoQXGBjI9OnT+eSTT+jXr186rQzIustCEASGDx/OuHHjtMYYYM2aNQZTpTOjQNES3M/kO1NqZqlNEZdZO+LkO5CHi3uhSXqtzW3ID5FappCr4kI5LWtpClKplHLlylGuXDntFiwxMZGQkBDOnDnDoUOHmD59Os+ePaN69epUqVWPQ9JaCELWViuCAAeuPqFt5x5cvXCaZ8+eUblyZby9valZsyb9+/enUqVKWFunF+l5H1Aqlfz000/alW5cXByPHj3SbsPfJtU4BgQEsH37durUqUPFihVxKVc9fYC/UxksnMoQrkpC1nYyaosEOnw1HCHiLjdu3DAqflUmk7Fy5Up8fHy4dOkSU6ZMITo6miNHjnDgwAE6depETEwMjRs35vbt25St3pqHBWpl/lwiIJdJEQQBY6SgBSBRqeGWrRfjp3clLi6OkSNHsnfvXsaMGcMff/yRY5lwxuDm5kbDhg0ZMWIEd+/epV+/fkyYMEHrVkhLVg/1duzYwcOHDxk8eLD22tOnTzl16pSOC8oUShUrxP17hr+M9ZL60U3zB33fKlbnuvzmu4rD1YeFhYXWv5xKZGQk586dY/mJu6iV6vQVLP4j5shqYo6sRuFUFIcGvbAo6aWnlUCxep8za/JP+dLlkAiwp6AAACAASURBVB1WrlxJqVKl8PHxAeDKlSt4enpmGNkwY8YMvL296devX8qB0s9LsW3Yh2S1oNcISuTmaIBbCVZYth6DInQn/v7+XLx4kZ9//pnSpUtnOMdKlSoxePBgBg0aRGBgII6OjnTo0IEOHToAcO/ePSZOnMiNGzdQ3LmDQ+ljFKzfnUgzV2QyKUmqN5OykEtRazSont5C5VJKR+xIUCkzLKEEIMgUTN55lR8DJzGoqx83btx4Zypmy5cvp1y5cuzdu5exY8fi4eFBSEhIOh0TGxsbk5KgIGWRM2LECJYtW6aT+r1hwwbat2+f5QVInQolOPLvlZRCpwYCA5Kf3kJqbo3cqQiaxFdEHViGeYnKSC1S3vN9LPGVJwL1uRmHm12cnZ1p0aIF+2IvcsFAjKqjz5conIsjkSmIv36M59smU/jLhdp02lTUyDB3LZFjcqD5hYSEBCZPnkxgYKD2mr4P9NsUL16coUOH8uOPP9JmxAys6vXUMXqGkEilKAVI9mhOi0qeuJtHU7NmTTp37sz48eMpUqSIwb5jxoyhWrVq/PHHH3Tu3FnnnlKpZOfOnRw/fhxPT08uX75McHAwew/v5HKcJc7uXjgXLkbJwgWp51mKLjVLMmpbAYLDnuuMk1EJJblDmoNkqRzL6u25fPkfQkND+fTTTzP93XMDd3d36taty5AhQ7h16xb+/v6MHDmS4OBgHf91VlwWc+bMoWrVqjRt2lTn+urVqzMUEsqMjtWLM2PvNQQMKyYqnIsRfXQNmtcxSM2ssHDzzpZiYn4gT0s4ZTcONzfJKLvQvMgbA2tTuQnx146S8O95FDXapGv7vvmsjGHx4sXUrl1bJ4Lh0qVLmeoOA/zwww9U+LQFF3deRSW8CUu8P6ejTjtBlYxt1VY4NftGe00iN+dMclFcpAlcvHiRhQsXUrlyZfr168eoUaO04vtpMTc3Z8WKFXz22Wc0adJE2yY5OZlu3brh7++vraad6sv//vvvSUxM5NSpUwQHB3NgzUJ2hYcT2MiXfz2/AHTDKTMsoaRjkKVYla1JA9dC9O7dm0KFCjFq1Cj8/PxyTTrWECtWrKBChQocPnyY/v37s3jxYnbv3q09cwHTXRYPHjxg3rx5vH3Qf+nSJWJjY2nQIL1kqzEolUrWr1xC0p0oFG41MlRMtK7YUO/13FZMzC3y9qnIxxiTXahFIiFVeCb9OO+XzyozYmNjmTVrFpMnT9a5bswKGVJ0bit1HknyWw7YEt9t1b6KDVmHRG6G1X8VuNMiUZjzd6wNPj4+NGnShMuXLxMXF4eHhweTJk3Sm1lWp04dOnfuzHfffae95u/vj6urq46fMy0WFhY0btyYadOmce7cOe7evUvZZr0QhMwdx2lLKL2NFLDxasqNGzcYPnw4kyZNwtPTk1WrVpGUlJR+sFzCw8ODWrVqMWjQIORyOXPmzOH7779HqXyzgDA1U+/HH39k8ODBuLm56Vxfs2YNvXr1MvlLJzUcsFKlSuzdu5dZX/giqNMnghhDflBMzAqiQf6PlCyu9P87NImvSLh9AUGVjKBR8+rqYZIehGJZqlq6tu+jzyoz5syZQ6tWrXQiKdRqNaGhoelSxPUR8SqJW6/NIYMP5+vwk8is7DEv7qnnroTXDqWZNmchgwcPZvjw4YwfP54zZ85w8+ZNypQpw9y5c9NFY0ydOpUjR44QFBTEoUOHWLNmDb///rtRIWaCIGBlZYXGrhAaScZf1PpKKKUlVYxIJpPRqVMnzp07R0BAAFu2bKF06dLMnDmT2NjYTOeUEyxfvpzw8HBOnTpFixYtKFmyJEuWvNHjNsVlcezYMU6dOpUuGUepVLJhwwZ69+5t0twuXbpE06ZNGTNmDAsWLGDbtm1sWTKL5NMbUUhMCxp/nytW56nLIj+TNrswLYJGTcyxdSijHoJEisK5GAU+G4/COb1v6n30WWXE8+fPCQgI4MKFCzrXb926RcGCBY06pMqoOGcqr64cxLpSY4PGUgJEO3oQGhrKL7/8QpUqVRgzZgyLFi3i0qVLTJs2jZkzZ/Lll1/i4+NDUlIS8fHxdOjQgW7duqFSqfDz82PatGnEx8dn+nr9+jUymQyXz8ajcEv/xZuKvhJK+kjrxpJIJDRu3JjGjRsTEhLCrFmzKF26NF999RXDhg3L0D+eXSpVqkS1atUYMGAAV65cYfbs2TRp0oSePXvi6OhotMtCpVIxZMgQZs+enS6uf//+/ZQuXTrTqjWpPHnyhPHjx7N79278/f35+uuvefHiBQ0bNqTy/9s77/Aoyq4P39vSewdCE0gooUkxVBWkCLwUBSEQpVdFQHpR9JMmLYCCgNKRpiJNECH0jkIiobdAaAnphZQt8/0Rd8lmS3ZDggHmvq69SHaeeXYmw5x95pzzO6dmTSa8XZvfr53nnleDElExsbgRDfK/mKpoJnNwpVSfsAL3f1F9VuaYOXMmPXv2NHgktdRdAQWXYlWlxJEdE4Vnu09NjslSaZiz/CdmfrRSZzTHjBnD2LFjcXV1xdXVFQcHB5YsWcKCBQuoWrUqVapUwdHREaVSiaOjI9WqVcPR0dHil1wuZ+Tm8yaLEZlqoWQMU26s2rVrs379eu7cucP8+fMJCgqiS5cujBkzhmrVqpmc71n44YcfqFevHn/99Rf169enS5cuTJs2jXnz5llskJcvX46Hhwddu3Y12LZmzRqLco+fPHnC/PnzWbBgAf379+fq1au4uroSFRVFhw4dGDBgAJMnTyY6OpqZwcHsPXuFpUdu/ueZWsWNaJDzYKqimSW8qD4rU9y9e5e1a9dy8eJFg22WBvSg4FKs6VEHsPWvjsLNvDjm9eCmzPq/UJ3BtLe3Z8uWLYwePZrWrVsza9YsPDw8OHDgAJMnT+bKlSs0a9aMihUr8vjxY1q1akVwcLBFx6zFXJEsUy2U8qOQQoCv+bZj5cuXZ+HChXzxxRcsWbKEt956i+DgYMaPH1/kkuq6detSq1YtBg0axLlz53Q+7aFDh+Ls7FygDzkhIYEvv/yS8PBwgyeapKQk/vzzT5YtW2Zi71zB1saNG5k4cSLBwcGcOXNGl864b98+evXqRVhYGL165QbxKlasiKenJzmPrrM0tGGhM7VelE4jxSadflF5lrb0L+pjkjEGDBiAj48PM2bMMNjWvn17Bg4cSOfOBTd+NbfKBLi/bBCuwV1xqt3a7DymJLApKSlMmTKFn3/+mVmzZulWZ0uWLGHEiBEEBQXRsWNHfv31V86dO0eaEotvzPj0bBrPCidHrX+PqFLiuP99P5Ap9KqMaVso6aFWovxlPKHdOtO7d2+Ligc9efKENWvWMHfuXEqVKsW4ceOKNDPjzJkzBAcHExkZSc2aNZk5cyZ//fUXK1eupFy5cmZ92sOGDUMmk/Htt98abFu2bBnh4eEmxSDHjh3js88+AyAsLEwvDXDFihVMnjyZLVu2GGRnjB07FgcHB7766iurz9V8pxF9uXtxdhr5z2tZvMgU1KFAy8vgszLG1atXadq0KdeuXTPaAblMmTIcP37cwJVhjKWHbxK2/5rRVWbWvcvEbZ6C/yfrdFJXY1hSJObvv/9myJAh2Nvbs2DBAvr168ewYcNwdnbm888/J03hQbl3B5LqmOvjL+jG1Gg0rFmzhsl/RKOoUB9JIYyhtkjWp687sGbNGtatW4e/vz99+vShR48eBrWO86NSqdi6dSuzZ88mIyODsWPH0qtXryJR+tWoUQMnJydOnz5NZmYm1apVY9WqVbzzzjuoVCqj/vyIiAjatGnD5cuXjR5748aNmTx5soGy8tatW0yYMIFTp04xc+ZMQkJCdF8uGo2GKVOmsGXLFnbv3m1U+Xn48GFGjx5tkF5XECXpPhYN8jPyz73kEqEu/C/o3r07derUYeLEiQbb4uPjqVy5MklJSRZlLGjbPxkzyAl/fIegzMbrf6ON7PkUW7mUE+NbFPhoqVarWbZsGaNHj6ZcuXL8/fffODk5seb4Tb7edQmlBrOGVXtj9qntwm9zPuPatWu4vVYbRduxZKuti/SDYcEplUrF/v37Wb16NXv27KF169b07t2btm3bmlU8CoLAwYMHmT17NhcuXGDkyJEMGjTomZR/x48fp1mzZly+fJnAwEA2bdrE3LlzuXjxIgkJCQbBOkEQePPNN+nVqxeDBw82mO/69es0a9aMmJgYnWIvJSWF6dOns2LFCkaNGsVnn32mN29WVhZ9+vQhJiaGbdu2mWxEoFQq8fX15eLFi0ZrcBijpD3pWmqQxbQ3E2jVhSfGt2BUqwC61ClDy6o+dKlThlGtAjgxvgVLQ+u/dMb4/PnzHDlyhE8/NR5ki4yMpFatWhZXKNMGS40N92z7SYHGGEFjcbBUJpNRsWJFPDw8qFWrFkFBQYxdvoNZe6+hQlrgKlfbAmjJyUfckpahd+/eXDq2h887VMdeYd2tYiz1Si6X07ZtWzZt2sSdO3d45513mDFjBv7+/owePZoLFy4YnUubmfHHH3/w+++/ExERwWuvvcb48eN58MB8BxRTNGnShICAAPr37w/kfgkrFAoUCoXRwN7mzZtJS0tjwIABRudbu3YtPXv2RKFQoFKp+P777wkMDCQxMZGoqCimTJmiZ4y1da0FQSA8PNxsVyCFQkGrVq3Ys2ePRecWGZPM9N1XrDLGAJlKDdN3X+Gfe8lW7VeUiCtkET3atWtHu3bt+OSTT4xunzdvHnfu3GHRokUWz/ksJS9R57Dj07ct+uKLjY2lbt26bNy4kTfffJMVv+3n6xNppEbuNdoCKCf+Lgm75qNKegiAjV9l3FsNxsarHDZS+GVoE93nFufj79WrV1m7di1r167F29ubPn36EBISYtZIRUdHExYWxrp163jvvfcYM2YMVatWtejztBw8eJCWLVty8+ZNKlasyMmTJ2nWrBkREREEBQXpxmVkZFC1alU2btxI06aG4h2NRkPFihXZvn07jx49YvTo0fj6+jJ//nyjwV9twahu3boxbdo0i3zja9euZdu2bWzdurXAsYPW/cWfF+4Rv9d4vZHs+1dIPrqenEc3QCLFrlxN3FsNRu7kUWAt9sIirpBFrObo0aNcvnzZZPNNsC7lTYu2FKu1q0xbmQS7y7stMsYajYY+ffrQr18/Xdfq0+luSOQ2uhZATrVa6e0jd/LAu/NE/Eduwn/EBuyrvEH89tkAKAVYcuiGbmxocAU2DwqmTXVfbOVS7PKJiKSCCkGVQ4sqnmweFGzVY29gYCDTp08nOjqa2bNnc+bMGapUqUKXLl3Ytm0bOTmGarUKFSqwcOFCrl+/Trly5XjzzTfp3LkzJ06csPhz3377bV577TX69+9PfHo2kTk++HQcS7/VZxi5+TxLD98kIT2bmTNn0rx5c6PGGHJFInZ2dkyYMIFPP/2UmTNnEh4ebtQYHz16lObNmzN+/HhmzJhhcaDy3Xff5cCBAwWqG+PTszl87TEa9dN6I2VHbcateSiPt3+DKjkWTVY6TnXaUmboSsoMW4nExp6E3xcA+p1G/gtEgywC5PoIJ02axJdffmk2aGRNylteQoMrMLldNewVMqPui7xIJLn+14H1PdFcPWzR/N9++y1JSUlMnToVeHpjCuS2AHIIaITU3kVvH6mdE3I3X537RSKR6lbLxm5Mc26sPvW8ebxiCLVSTxfajSWTyXjnnXdYv349d+/epUOHDsyfPx9/f39GjBjB+fPnyf9E6+npyRdffMHt27dp3bo1oaGhNG3alB07dqDRFPzIPnbmd0S5N6bxrHDC9l/DJrApcQpftkU8YMH+azSaFc7qGwr6jv7S6P5xcXEMGTKE+/fv8+677xIVFUXHjh2NurQ2bNjA+++/z7p160y6Pkzh7e1NtWrVOHr0qNlxWiGStt5I7vWV6tUbsa9UH8eqTZHaOiBV2OFcrwPZ9y/r5pAAv5wrWNBUHIgGWQSAPXv2kJCQYLbnWnZ2NtevX6dGDWMS54IpaJUp0aiQoaFNdV82DwqmW10/swXqtURGRjJt2jR++uknXUDJEoWglrth3bk7pwuJ+5bh0qib3jZjN6a2SFZY9zqs6N2AsO51+KJbY/y9XJk3b56B0SwMLi4u9O/fnyNHjnDy5Enc3Nzo0qULtWvXZv78+cTGxuqNd3BwYNiwYVy7do3hw4fz1VdfERQUxKpVq0yuKtefimbBBXCo/AY5asEg8Jql0pCjFpBXrMfwbTdZfyr66basLL755huqVatGdHQ0Z8+eZcSIEdjY2Bh8jiAITJs2jYkTJ3LgwAFatWplMMYS2rdvz++//252jCkhkrl6I9kxF1F4PX1fK3f/LxCFISJoNBomT57MtGnTzNZwvnTpEpUqVcLOzs7kmILIX4r10oMUdv6xn3q1qlPexYbwH2ewdGbuKiguLqdAg/zkyRNCQkKYP38+lSo9TYsrSCGYl3KjNqPJySIjKhyZy9OOF9kqDet3HaShcyqlSpXC09NTr+ZvfoYOHcrXsxcwduVeVE6+RSZAqFSpEl999RVTp07lyJEjrFmzhsDAQJo1a0bv3r353//+p3uqkcvldO/enQ8++IADBw4we/ZspkyZYpCZoZeFUKDbQEKmUs303ZcRBLCNOaPrdjNhwgQOHTpkUlmYk5Ojk2qfOnXK4iwJY7Rv354PPupP4OGbennkgb7OtKhgT2byY27cNQxymqs3khN3m5TjG/F+X7+t1X9VtVEM6omwefNm5s6dy5kzZ8xmT6xevZp9+/bx008/Fenn//HHH3z66adERkZSpUoV/vjjD4KCgkhLS6NUqVJm5bxDhw4lNTWV9evX6x17vzVnOZCvjnH+nmz5EQQN9xb2ovTA75E55rodlNHnePzr1zg4OJCRkYGjoyNeXl4GL41bWSKUvtx8Ypt7HHk6lReHACE9PZ1ff/2VNWvW8M8//9C9e3f69OlD/fr1Da5hREQEs2fPZu/evQwYMIDWIQP5ZOsNYrZ+Q1Z0JBplFjJHd1yC38e5dhuzwU6JOgen0z+ycOpoWrRoQevWrenfvz/du3c3OMbk5GTef/99HB0d2bhxo9XF6jUaDQkJCTx48ICTVx/w27UnXEmRIpVK9RoGaJTZSCQSFPHXkNnYk+3x9ItZEDTE75iDJvsJPu9/ridxVyY9IPanCbi91QenIP2+jUXdi0/MQxaxCJVKRfXq1Vm8eHGBj5IjR46kdOnSjBs3zuy4wtC+fXtatGhBfHw8KpWKOXPmoFKpsLW1NSlU2L59O6NGjeL8+fMGObnGFIIFGmSNmpj53fALnYONX+5N3aVOGTr6JDF58mRSU1OZOHEiDRs2JCEhgfj4eOLj4zkYo+JYhg9qJCAxs9oUNEgENQEZUdR1Sjdq2L28vHB1dbWq8Wl0dDTr1q1jzZo12NjY0KdPH0JDQw0KFd2+fZuwsDB+jfNEUeF1cuJjULiXRiJXoEyI4dGGifh0+xKFmx+arAxkrj4gaEg79zvpkX9Suv93gECb6n4s+7A+9+7do1atWty/fx97e3uDY2rXrh2tWrVi/vz5ek9egiCQmJjIgwcPdK+HDx8a/P7o0SOcnZ3xfKMzOTU6IEhlZv++gkaDBA0gAans33ojC1GlxOLT7Us9ibsqJY5HP03AtVFXnOu205unOLpV/+dNTkVeDFavXo2/v79BxwdjREZG0q5duwLHFYb58+fTpEkTtm/fTrdu3Zg5cyZyuRypVIpSqTTwTd6/f5/Bgwfz22+/GRVI+DtJkGhUCFK5yRZAWXf+QWbvgsKnAoIym+Qj65DaOaHwyn2s1ZZTfbt5HY4fP87vv//O5MmTsbe3Z8aMGXTo0IH1p6I5c+syaokF7hGJFEEi5ZZLbXxsH6B6dJ2oqCidYde+MjIy8PT0NGmwjb2mTJnClClTOH78OGvWrKFGjRoEBwfTu3dvOnXqhL29PRUrVuSLGXP44185uI13+bwHhwQJqqSH2PpVRmqXW39DEPSDnSBh3+VYhv70F4nXI+jYrafOGAuCoKtn8fHHH/Puu+/i5+fHyJEj9Qzuw4cPcXR0pHTp0pQuXZpSpUpRunRpAgMDefvtt3W/+/n58UvEo1xXiQU5xbl55k8Ntql6I6q0eGI3TsK5XnsDYwz/bdVGcYX8CpOVlUVAQABbtmwpsPCOIAh4enpy+fJlfH19zY4tLJ999hnp6elERkYyevKXJLoG8NXCH2jVriMezvY6X6y7Q65Q4K233uLzzz/Xm0Or1pvy9Te4fLgQZAqSj/6k1wIIyG0B5F2e5CPrUafFI5HbYFOqCu5v9cHGpyJgXCGo0WjYsmULn3/+Ob7VGxJXsyc5+dKrVcmxJPy5hJz7V0CuwDGwCe7vDNKre5FfxZeXnJwcEhMTDQy1uZdKpdIz0O7u7qSkpHDz5k0ePnxIo0aN6NSpE4+96rD5UrquPkfC3iVkXAhHUGVj41sJ316zkNrkGti7Yd0RcjJBEHBt1gu3Jj30jlNQZiOVybBNvEn2+R08ungaqVRKdnY2QUFB1KpVS2dc8xrfUqVKGayojXH8yj36roskxzp9R+41MFNvRJX0kJRjG5Ao9GMh5Ub/8p/nIYsG+RUmLCyMQ4cOsX379gLH3r17lzfeeIOHDx8WOLawJCcnU61pW17731AeaNyxsVEYrTlRWpLMk79+48TOjXqPwmfPnmXAgAHExcWRnZ1NnU8Wc1vpYqK3i3kKujGVSiUdvtnOlTRbAwVg7JapyBzc8Gz7MZqsDGI3T8Gpdhtc6ne0eH5ryczM1HOj5H1FR0dz7tw5bt68ieM7H+OQr+2RoFGTff8KWXcv4BrcVc/PmjfY6VC5Qf6PzT0XwEYmoaEihoM/fM327dupV6+e1ecQFxfH0aNHOXLkCEePHuVh5f9hU642CfuWmmwomxa5l9STv6DOSMLWvzqe7UYgdzZs7WUp5r4onwXRZSFilrS0NGbNmsX+/fstGl8YQYi17LqSjGPHydzXAFKp0TQsgFsaJ+zq9WHj2RhCgyuQlJTE2LFj2bRpEwBDhgxh0qRJxGRIC60QLKicakq2huhsRyRSw+WbKiUWl3odkMhtkDnZYF+xHsr4u3pj8uY5W5N9odFoSE1NJTk5meTkZFJSUnQ/G/td+15GRgZ2dnZIbAxXphKpDLuyNci4eJC087v1vjikNnY41X2Xewt7YZsn2Kl3LkC2WuBItjftR8wiIyODS5cu4eXlhYeHh9E6HYIgcOfOHT0D/OjRI5o0aULz5s2ZPm8RIw6kkfXkicmGsqrUOJIPr8U3ZAYKj9Ik7l9O/I45+PWaZfHfMy8lodOIaJBfUcLCwmjVqpWu4WdBFFYQYinaNCyVIM1dcplBIpWSrRKYvvsyJ06c5Kevhui6gnzzzTe6KnQeHjC5XdVCFpkxf2Oay3N2qd+RjEtHsC1X898WYH/h1swwv1sQNMzafJBgtwyLjWt6ejpOTk64ubnpvVxdXXU/+/v7ExQUpPeedsz/7bvLjn9MPOVoNHl8xRC/cy5Z0ZGoczJBmUXq37twbx5qVnr8Z7yUiJnfkhqd6xtPSkrCxcUFLy8vHB0dUavVZGRkEBeXmwFTtWpV6tSpw4QJE2jYsCG+vr64u7uz/OhtJKSZbSib8+AKDlWb6nzhro17cH9xb5RJD1G4l0Iuzf2PpBaE/7zam6WIBvkVJCEhgUWLFnH69GmL94mMjOT9998vluMxVgwm9e+dRutP5CVTqWHXAxsqNXibFXOmUrduXYMx2husqOtQmMtztitbk/SIvcTM/wAEDY5BLbEPaGQwLkcNO4+e52LcUTw9PfH09MTd3Z1KlSoZNbRubm44OzubzRUviOqlU9h7KZYnKYlk3YnEvnJDJHIbsqIjyLh8GK//jSXz9nlk9i44N3wf9xYDSTmxiYzLR0iL2INDQLBOemxf8XWQSkn8cykJvy/At/v/gUxB3V7j+a5HHc6fP8/hw4c5ePAgJ06cICMjg8DAQOrVq4e3t3duFkRCArGxsSxfvpyZM2cSHx9PSkoKfp3HI69iWJw/r8Aj+/5l9C9o7s/Kx3dQuJdCpRF4K8AbO4X0hanaKBrkV5BZs2bRrVs3PSFFQURERPB///d/xXI8iw/dIEul71bQ1p/IvH0OQWm687BMYUfDPlOMGmMtocEVqOXvVqTlVE11QhEEDbFbvsC5Tlv8PpyLRplJwu8LST60Cve3+xmMz0HG+fPnSU1NJTs7G2dnZ1xcXHBxccHV1bVQP9vb25tMm9P1jpRISDu/h4S9S0DQIHf1wb3lQBwCgsm4cozEfcv0gp2ebYeTuHcxqqSHOFZrpjenc70OxG6Y+O/5w94L9/H8rBPlfD1o1qwZH374IcuXL6dMmTK6fVQqlV7gUuv/TkhIIC4ujgOqsuSvuZZf4GFfqT7x22fjXPdd5O6lSTm+CZAgqJ4qE2VSiZ4QydpOI88b0SC/pJhqWdO0jJwVK1aYLPVojLS0NB4+fGi0eHhRHOfha48NVq4Ogbmro+xHN1Ar403uL2CZLza/QvBZb0wXO+O3jiYzDXXqY5xf74BErkAmV+BU6x2Sj6wzapA7vduasNW5ed0qlYrU1FTdKyUlxejP169fNztGpVLpjLQxo+3h3IBsO2+TvlbHqk1xrJpbSEibhZF1629sfCvpgml5yS89lkoldBg+jRqyhyQkJLBnzx7Wr1+vZ3zT0tJwd3fHy8tLL8XP09OTUqVKUVbpTXIe9bKxhrL2Ferg1rQnj3+bgSb7CS4NOiGxtUeWJ6in7WeolbuXdESD/JJhvmXNI2YrlVQbOJ94jSNlTE2SjwsXLlC9enWzRdQLizU1J0yhLQZjyQ1XVDemqX57MgdX5K6+ucGxN95DyMkk/UI4in9T6fKizXPWIpfL8fDwKLCTSEHk5OSYNOxRUVHc/O17HDpOAgzrTuTHs80wPFoN1mVhSGT60nFjVFNCtQAAIABJREFU0mM1Mm4mZFHWLldyHhQUpGdwvby8cHNzM1vpzfnwTa7922nGXENZ53odcK7XAQBl4n1STmxG4V0BMPz7vgiIBvkloqCavVkqDUhkPJB40+OHUxYHMYozoGdNzQlT/BfFYHSP/kbwfm8yifuXk3rqF5DKsCtXE4+WhiVNi0uAYGNjozOAus8SBH788Ud+/PFHFi1ahLpiXYuDnaayMJRJD4jbMhX3dwZhVzZIb5/AmnWY1X9ooc8h79/XlMBDUOWgTHqAwqs86tTHJOz5Fuf6HZFpRS38dwKPwiIa5JcEa1rWCKArFgMUaJSLKuUtMzOTmJgY7ty5w507d7h79y5HUsuCfemCdy6A510MRtsJZd/lWIMvPxvf1wpMvZJIsLgTyrOSnp7OkCFDiIyM5OjRo3qF7L/YFokGGQXWRAW9LAxVShyxG6fg2qSHQR0IgP27dzAqagvDhw/XdZW2Bu3fd8+pC6RH/AEyBfe+/VC33aPtxzhUakD8jrmokh8isbHHqeY7umyW5/n3LUpEg/wSoM1SiD213WhmQvrFgyT+sfjpDoKAoMrGr88Cpu+WUMvfzWwgKyIigg8//NDk9twpc+sT3L17V8/g5v03OTkZf39/ypcvT7ly5ShfvjxlfNxJLILFrdZX+Dz5+K3KHL0eXyx5zkVFVFQU3bp1o1GjRpw+fVqvjVJtxzSe7JhB+7ELOXYrSS/Yqc5INpmFUZD02E4uZehHXUk8sYWGDRvStGlTRowYwVtvvWVVjQ7t37f8hF0mx+TW1zDkef19ixrRIL8EaLMUTGUmONV4W689ffo/+0k5sQkb30pkqdQsOXTDpGJMrVYTFRVF9erVuXv3roGRzfuzTCajfPnyega3YcOGup/9/PwM/IZL8/gK82Kq/kReGawWuUSgirfprtXFhbYTSnHkORcFa9asYcyYMcyZM4c+ffoYbB83bhyThvTi077BJKRns/rIFX47cp4YwcNsFkbysQ2okh+RcmwjKceeStLLjf4FyH0CG9AyCM9O9fjiiy9Yt24dw4YNw8bGhhEjRtCzZ0+LSrgW9u+rkAj/ucCjsIjS6RccY12dC6pq9mjDROzK1cStaU8gt2ZD+KeNSIt/aGBwL1++TGRkJBKJBC8vLwODq/23fPnyheqCbKortan6E3lFAlokGhUZGz8jtGsn+vXrp9cP7nlgab89QaPB3lbOlGLqbKzlyZMnfPLJJ5w8eZKff/7Z6N9j//79DBkyhEuXLpGYmMjcuXNZuXIlISEhpNbuztFbKeYr15nAlCRco9Gwb98+Fi5cyN9//82gQYMYOnSoQUU6Y1jTz9BGKiHtyBpWTupL27ZtrT7+4kKUTr8iWJuloEqJIzvmIp7tRujey8rKpFbnQXjGndczsi1btqRChQp4eHiwc+dOs62dCouXky1VHHO4kKTfFdqtWS+jxjc/Egm0qVmGMQP3smrVKtq0aYO/vz/9+vWjR48ehfqSsJaC8pzlEg1qtQbH5Nt81MCvWI3xlStX6NatG7Vr1+bs2bM4OTkZjNFoNIwbN46xY8cybtw41q5dS2hoKP/88w/+/v5ExiRzcslRjGdam8eUq0AqldKmTRvatGnD1atXWbRoETVq1KBdu3aMGDGChg0bmpzT2jzy9HZudOrUiR07dtCokaEgpyQjrpBfcKyt+5t8fCNZ0ZEGQafOdUqzoLuhuGLSpEnY2trqetUVJZmZmYwaNYp9f19D1ma0QdU0S8hfDEatVrN3715WrlzJ/v376dQpd9XcvHlzq/yXhcVYnnN5Vzlf9m7LkrDZfPfdd1Y1IrWGDRs2MGLECGbMmMGAAQNMnu/ChQuZOXMmOTk59O7dm3Hjxhl08pi86g82XM5CkFnumxeU2Qxr5Mf49w0VdsZITk5mxYoVfPvtt5QuXZoRI0bw3nvvme3KYmke+e7du+nXrx/h4eGFbjlWlIgr5FcEU4oxU2REHcC10QcG76eZmCciIoLBgwcX6tjMcenSJbp3705QUBDnw7ex41JikfhiZTIZ7dq1o127djx+/Fjnv8zJyaFv37707t1bTzFW1JjKcz7wxutkZ2dz7949zp8/b1ZZaC1ZWVmMHDmS8PBw9u3bZzJF8e7du0ybNo0VK1bwwQcfEBYWhp+fn9Gxn7StzYoVn+LWot+/ucCmP18CCOocfO4fZcEnm+gcdIjAwMACj9vNzY3Ro0czYsQIduzYwcKFCxkzZgwff/wxAwcOxNPTsGqbpXnk7dq1Y968ebRt25ajR4/q6puUdMQmpy84phRjxsi6dwl1eiIOgU2MzGN8VVLUVd4EQWDlypW8+eabjBw5kg0bNuDi4lKortSTC/DFent789lnnxEVFcX69eu5c+cONWvWpH379mzdupWcHNOS7KImJCSELVu2MGTIEBYvXlzwDhZy48YNGjVqRGJiIn///bdRYxwdHc3gwYOpW7cu169fp02bNmzcuNGkMQbw8/NDefkAS7sG6prS2uSzFrYyCYIqhxYBHmzs3xDbmLNUqVKFli1bcuvWLYvPQS6X895773H48GF27NjBlStXqFy5MoMGDeLixYsWz5OfXr16MXbsWFq3bq0rZlTSEQ3yC06uYiz3MgoadW42Qp7MBEHz1A+QcSEch4DGSG31MxJMKZoeP35MRkYG5cuXN9hWGFJTUwkNDWX+/PkcOnSI/v376z1WF9SV2k4uxVYu1XWlttQXK5FIeOONN1i2bBkxMTF0796dhQsXUrZsWUaPHs2lS5eK5PzM0bFjR06ePEmnTp349ddfSUpKeuY5f/nlFxo1asSAAQPYvHkzLi4uettv3rxJ//79qVevHl5eXpw8eZKoqCjCwsIKnFsikVCjRg3Uj2+zNLQ+J8a3YHSbqjjHXybzxhm61CnDZ60DqX9/G3Uz/qZRYBn++OMPpFIp/v7+tGjRgpiYGKvPqW7duqxevZorV67oOtm0atWKXbt2odFYLyD69NNP6dGjB++++y6pqalW7//cEQTB4le9evUEkZLF47QsIWDKbqH8hF2Ca5MQgdysI93LtUmIUH7CLqHcmK2CxNZR8OkxTSg/YZfeK2DKbiE+Lctg7n379gnNmzcvkuP866+/hMqVKwuDBg0SMjIyChwfn5YlLD18Qxi56bzQb/UZYeSm88LSwzeMHmdhuXbtmjBx4kShVKlSQnBwsLB8+XIhJSWlyObPT0hIiLBkyRKhZ8+ewvz58ws9T1ZWljB8+HChYsWKwtmzZw22X7t2Tejdu7fg6ekpfP7550JCQoIgCIIwYsQIYdiwYRZ/ztChQ4UFCxbovXf8+HEB0F3DAwcOCEFBQYJGoxEEQRAyMjKEli1bCnXr1hUqV64sPHjwoLCnKQhC7rmuXbtWqFevnlClShVh0aJFQmpqqlVzaDQaYciQIcLbb78tZGZmPtPxFBbgL8ECGysa5JeAgWvPChUm7jIwtJa8KkzcJQxeZ3hTC4IgzJkzRxg+fPgzHZtGoxHCwsIEb29vYfPmzc80V3GhVCqFnTt3Cl26dBFcXV2F3r17C0eOHNEZmaJix44dQrNmzYTjx48LlStXFtRqtdVz3Lp1S2jQoIHQqVMnITExUW/b5cuXhdDQUMHLy0v46quvhKSkJN22GzduCJ6enkJsbKzFn7V48WJhwIABBu/L5XLdF4pGoxECAgKEY8eO6bY/efJEaNOmjVCjRg2hWrVqQlxcnLWnaYBGoxGOHTsmdO3aVfDw8BBGjhwp3Lx50+L9VSqV8MEHHwhdunQRlErlMx+PtVhqkEWXxUvAx29Vxk5euBq55hRNkZGRz1TDIiEhgY4dO7JhwwZOnTrFBx8YBhNLAnK5nA4dOrB161auXr1KzZo1GTx4MIGBgcyaNavI2la1adOGixcvUqZMGZycnNi3b59V++/YsYM33niDkJAQfvvtN9zd3YHcAGnPnj1p3rw5VatW5caNG3zxxRe4uT0Ndk6cOJGRI0fi4+Nj8ecFBQURFRVl8L6bmxvz5s0jJycHiUTCoEGDWLZsmW67vb0927Zto0KFCqjVat55551ndtFIJBKaNGnCzz//zLlz51AoFDRs2JDOnTtz8ODB3NWlGWQyGWvXrtXJyAsa/18hpr29JFhTy0JLbpaC6cBYrVq1WLVqVaH6ox05coTQ0FC6d+/O9OnTDbpGl3QEQeDUqVOsXLmSX375haZNm9K/f3/at29vNi2rIAYOHIh/5WrckZbi3K1HvB7cVFcatVs94yVAlUolEydO5Oeff2bTpk263NoLFy4wbdo0Dh06xKhRo/j4449xdjaMBZw+fZr333+fa9eu6UmnCyIhIYGKFSuSkpKi5+uvVq0anp6efPTRRwwaNIj4+HgqV67MrVu39CrVZWdn0717dy5cuICnpyfh4eFGj6+wZGRksG7dOhYuXGixCjA9PZ2WLVvSokULZs6cqbfNVMlaU9fFGsQmp68g1iiaCuqMkZ2djZubG0lJSRbJXLWo1WqmT5/OkiVLWLlyJe3aGdY6eNFIT0/nl19+YcWKFVy/fp0PP/yQfv36Ua1aNavmiYxJ5qufT3LuUTa2trZGG7i+FejNsDcrU7ts7upWG4R0d3dn7dq1eHp6EhERwddff83x48cZPXo0Q4cONSoAgdwvlubNm9O3b1/69TOsx1wQpUuX5uTJk3qB3YYNGzJo0CC+/vprrl+/jo2NDaGhodSvX5+RI0fq7a9UKgkJCeHMmTOUK1eOP//806ovBUuwVgUYHx9Ps2bNGDBgAKNHjy6gZK3x62Itlhpk0WXxElGUWQqXLl2iUqVKVhnjBw8e0KpVKw4ePMi5c+deCmMM4OTkRJ8+fTh69CiHDx9GJpPRokULGjduzIoVK0hLK7g60vpT0fT44RTn4zUgUxht4Jqt0vDnpVh6/HCK9aei2bNnDw0aNKBTp07s3LmT6OhoOnfuTLt27WjatCm3bt1i7NixJo0xwPbt20lJSaF3796FOndjbgsnJycqVqxItWrVWL16NQCDBw9m2bJlBq4AhULBxo0badSoEbdu3eJ///sfWVlZhToWU2hVgLt37+bIkSMkJiZSo0YNevXqxZkzZwzGe3l58eeff7Jo0SI+XrCJHj+cYt/lWLL/vQZ5MXZdihNxhfyS8qydMVatWkV4eDjr16+36PP27NlDv379GDZsGJMmTXqmvm8vAiqVij179rBixQoOHz5Mly5d6N+/P40bNzZQyBXGnSRDTc6pTfz01RDs7Oz4+uuvOXfuHOPHj2fgwIHY2xt2j86PUqkkKCiIhQsXFrquw2effYafnx/jxo3TvdepUyf69u2Lr68vPXr04Pr16ygUCmrUqMHSpUtp3ry5wTwqlYqPPvqI8PBwXn/9dbZv316sbixLVIBzt53m2+P3kcgtd0cU5OYzhaUrZDHLQsQoI0aMEGbPnl3guOzsbGHMmDGCv7+/cPjw4edwZCWPhw8fCrNnzxYCAwOFwMBA4ZtvvhEePnwoCIIgRNxNEqp+vkdwrPGWIHN0FyQ29oLcvbTg8e5wXaaLT49pgtzDX5DIbQXbcjWFMkNXCuUn7BKqTNolvNnlI8Hf31/47rvvrE7ZWrJkidCyZctnyhZZsWKF8OGHH+q916tXL2HdunWCIAhC69athWXLlgmCIAgLFiwQQkJCTM6lUqmEjz76SPDw8BA6der0XLIdlEql8OuvvwrNmzcX/P39hZkzZwrx8fFCxN0kIWDidsGxVitB5uItSGzsBYXPa4JPty9116Xs6F8Ep7rtBKm9iyCxdRBs/WsI5SfsEqp+vkeIjEkq+MPzgIVZFuIKWQQwDGicPnqQNm/UZHJIC5Mr6lu3bhESEoKPjw+rVq3S61DxKiIIAidPnmTFihVs3bqV5s2bIzQZwIVkKdlxd1C4l0YiV6BMiOHRhon4dPsSuYs395cNxPPdT3Go3JDkI+vJuneRUh/NQ9BoCHTMYuf4jlYXdkpLSyMgIIDdu3c/k0z7zJkzDBkyhHPnzuneGzJkCLVr12bo0KGcOHGCkJAQrl+/TkZGBhUrVuTGjRsm/y9oNBoGDhzI1q1bad26NRs3bjTbyqkoOX/+PAsXLmT79u1U6TubWIkHKad/xanmO8hcvcm8+RfxO+ZQut93yN18id85F0GjxqPVEKR2TuTE3cbWr7LJinbmEH3IIhYRGZPMoHV/0eSbA4Ttv8a2iAccuBJHhncNfr8j0PibAwxe/xeRMfo9gH/++WeCg4MJCQlhx44dr7wxhtzULK1fOSYmhnfad+afhNw6EDbe5ZHItY/LEiRIUCU95Mm1k9h4lcOxalMkchtcm/ZEGXcbZUIMEqmUO0on0gvRDGX27Nm0atXqmWtmVK9enStXrqBWP1V8Ojs76/zmjRs3pmrVqqxevRp3d3c6deqk8ysbQyqV8sMPP9CtWzf27NlD3759n1sKmlYFeOLcBRJs/ZDY2OHWrBdyN18kEikOlRsid/Ul+9ENlAn3eHL9NJ5thyNzcEUilWHrl5seKghPG+sWNWJxoVeYgrIystW5gr8/L8Vy5Fo8k9tV5f3avrpCNrt376Z+fctXCa8STk5OKAKbYxvztPi+toOzoMrWdXBOPrxWrwGq1MYOuZsfOY/vovAsa1UDVy33799nyZIlnD9/vkjOw8/Pj5s3b+q6jjs5OZGenq4bM3XqVEJCQujTpw9Dhgyhd+/ejB492mS1OalUyrJly5DJZKxbtw47OzuWLl36XKrxARy+m41cLkedL4CnzkhCmXgfG+9yZD+4itzVh+SjP5Fx8SAyJ3dcm/TEsWpuHZjCXBdLEFfIryhPA03mU+Qgd0WQqVTz9a5L1Ok6nLS0NM6dOyca4wLI38DVs80wyn62Bd9e32Af0AiJTIFGmYXU1lFvP6mtI0JOJlC4Bq5Tp05lwIABlCtX7tlPAsNMi7wrZNBfJQcHB2NnZ8fBgwfNzimRSFiyZAl9+/Zl3bp1jBgx4rmtlI011hXUKuJ3zMWpZksUnmVRpyWgfHwHqa0D/p+swaPVEBJ+D0MZn1ufo7ga64oG+RVE24PPmqg/5K6YNbU7M/6bxQaFbEQMMVYaVdvBWZ0WT9r53UgVdmiyn+iN0eQ8QWLzNIvCmgauUVFR7Ny5k4kTJxb+wPNRkEGG3C+BGTNmoFQqdSlwBSGRSFi0aBGDBg1i+fLlTJgwociO2Rz5r4sgaIjfNQ9kcjxaDck9NrkNSOW4NumBRKbArlxN7MrVJPP2uTzzFH1jXdFl8Qqy+NANMrOyiN+7hKzoCDRZ6cjdSuH+5kfYV6qPoFYSv2MO2Q9voE6NwzdkBnblawGgQsL3h29aFdB4VTFbGvXfDs4K7/JkXAh/+nZOFqqkR9h4P13dWtPAddy4cUyaNElPNv2sBAUFsW3bNt3v+V0WkLtKDgwMZM2aNYSGhjJlyhRiY2Px9fU1O7dEIiEsLAyZTMaCBQuwtbXl//7v/4rs2I2R97oIgkDC7kWoM5Lx6fYlElnuNoVPBQvmKfrGuuIK+RUjPj2bw9ceo1GrkTt74ddzFmVHbcateSiPt3+DKjkWAFv/Gnj9bzQyR3e9/YszoPGyoS2Nqs5IJuPSYTQ5mQgaNZm3/ibj8mHsytfGIaAROfF3yLhyHEGVQ8rxjSh8KqDwLAuYLo1qjPDwcK5du8bQoUOL9DwsWSFD7ip5+vTp2Nvb895777Fq1SqL5pdIJMybN4/hw4cza9Yspk+fbjAmPj2bpYdvMnLzefqtOcvIzedZevhmof4f5i1Zm7h3McqEGHy6foFU8TSTxa5sEHIXb1JObkHQqMm6d4msmCjsX3s9d7sV18UaxBXyK4a2B5/03wizlrwRZke3Jrg06JS7wUhKUnEFNF42utbzJ2z/NbMdnAG8u0wi8c+lJOyah02pALw7PhVhCEDX1/0L/CyNRsPYsWOZOXNmkQsuAgMDuX37NtnZuZJvUwY57yp58ODBhISEMG7cOIvT2ubOnYtUKuXLL7/E1taWMWPGFCBrfkTY/mtWy5q110WVEkd6xB8gU3Dv2w912z3afoxTjbfxfn8KCXsWkXrqF+QuPni1H6X7orT0uliLaJBfMYwFNEA/wlwQxRXQeNnwcrLlzQBv9l3WGPQwzIt9hTqUGbTU4H2JJLdxpyXKyg0bNmBjY0PXrl2f6ZiNYWtrS4UKFbh69Sq1atUy6rLQMnXqVHr27MnVq1dxdXVl//79tG7d2uLPmj17NlKplAkTJnBZ6cmJzFIms4C0jU7zZgFZoqDLe13KT9hlcpyNd3lKfTTP4H1rrou1iC6LVwxjgab8EWbL5in6gMbLSHGVRs1LVlYWkydPZu7cucWWOpbXbWFqhQxPV8lr1661OLiXn1mzZtF57Fz2JbhYlQU0ffdli2tNPI/rUhhEg/yKkT/QZCzCbNk8RR/QeBmpXdaNye2qYq+w7lazM9LA1RSLFi3i9ddfp2nTpoU9zAKx1CDDU19y165dOXDgAA8ePDA51hiRMclcVFQl/Z99PFw9kjtzOhO/y3jbqeRjG7gzqwOZ0RFkKjVM332Ff+4lGx2bl8JeF2ONdYsS0SC/Yuj14MsTYfbuMkkXYS6I4gpovKxY28BVolbS0iPFosfvhIQE5syZw6xZpl0iRUFeg2zOZQG5q+SAgAC2bt3KBx98wMqVK636rMWHbpClUiN38sS1cXecarUyOk6Z9JAnV48jc3pagzlLpWbJoRsWfU5xNNZ9VkSD/IrRtd7TQISpCDOAoFLmNkwFBI0qt2Hqv8+OxRXQeJmxpjTqmLpyzm6Yb9G806ZNo1u3bgQGBhbHYevIa5AdHR3JzMw023RUu0ru168fP/zwg5702hzaLCBBAIfAxjgENEJqbzznPXHfUtzf6gPSvGls1mUBFVdj3cIiBvVeMbQBjT2nLpiNMN9fPhh1am7r9LjNXwBQZsgKFO6+xRbQeNmp5e/G0tD6BZZGVavVzJ00nLNnz9KgQQOT8928eZN169Zx8eLFYj/2SpUq8fDhQ9LT03FycsLBwYGMjAyTHUCaNGlCQEAA//zzD76+vuzdu9ei+tjaLKCCyLhyDIlUjn2lBsD3etuszQKy9Lo8D0SD/Ary8VuVOXo93myE2X+Y8cfM4gxovCp4OtmaNRYymYyhQ4eyePFis4V6Jk2axMiRIwsUXxQFcrmcqlWrcunSJRo2bIiTkxNpaWlmWzJNnTqVXr16MXHiRJYtW2aRQTaVBZQXTU4myYfX4NP9a6PbC5sFVNB1eR6IBvkVRBvQKFwPvuILaIg8pV+/flSpUoXrdx8RfjvDoM9bJUkcx48ft1h8URRo3RYNGzYsMLAHT1fJSqWSY8eOce/ePfz9zbu6jGUB5Sf56E841miBws3PzDwvZhaQaJBfUbS+sKLqwSdStNzPlFOp9yzafn8WuVxuIIjIysmhxpCFXE/IoXYR96gzRVBQkM494uzsbDawp2Xq1KmEhobSrVs3fvzxR7788kuz483Kzf8l604k6rQE0s7/DoDmSSrx22bhEtwV1+Cu/87zYmYBiUG9V5iSFtAQyUXbfy/B3h81UqN93pDKufbE7rn0edOSP9PCkl6CTZo0oUqVKvj5+fHjjz+iUplfAetlAWnUuYFljRoETW5gWaPGN2Q6pfsvpnTfbynd91tkTh54tP0E59fbAy92FpC4Qn7FKUkBDRHr+u/lFUQAxf6FaU0ucl60q+QyZcqwe/duOnbsaHKsTm4OpBzfRMrxjbptGRcP4tokRE/yD4BEitTOCem/FfJe5Cwg0SCLACUjoPGqY6osqjI+hoQ/vycn9gYye1fc3+6LQ2Bj3XatIKKWv1ux+vfLlStHWloaiYmJFrss4Okq2d/fn2XLlpk1yE9lzbG4NetlaHyNkDcAXZyy5ueB6LIQESkhaAUReRE0auJ+/RqHyg0oO2IjHm0/IX7XPJSJ9/XGWSOIKCwSiYQaNWpw8eJFi10WWqZOncqBAwc4deoUd+7cMTu2pMqanweiQRYRKQHkFUTkRZkQgzo9EecGnZFIZdhXqI1tmepkRB3QG/e8yqJq3RbWuCzgacZFnTp1+PHHH82OLamy5ueBaJBFREoAJgURRrNfBHIeG64ytYKI4iSvQbbUZaFl6tSpXL16lR9//BGl0nxaWkmUNT8PRIMsIlICMCWIUHj6I3NwJfX0rwhqFZm3z5F1NwpBZbgSfh5lUbUG2VqXBeSukqtVq4aTkxM7d+4scPyrmAUkBvVEREoApgQREpkc7/enkLhvGamnfsWmVGUcqzUFmfE82+IWRGgNco8ePbhxw3qf9dSpU+nSpQvff/89zVu355e/7xmIXrrVe5rZ86plAYkGWUSkBGBOEGHjU1GvwP2jdWNwDGppYp7iFUT4+PggkUhQq9VWuywAmjZtSkCjVkTZVaHxrHAkEolFXUBelSwg0WUhIlICyCuIyE9O3G0EVQ4aZRYpp7eiSk/CqeY7BuOehyBCIpEQFBREQkKC1S4LyM2zflyrFzYV65OjFoyKXrJVGv68FPtcRS8lBXGFLCJSAsgriMhPRtRB0iP3ImjU2JatgW+Pr5HIDVfCz0sQERQURGxsrNUrZK3oJUcNkgL67D1v0UtJQTTIIiIlgLyCiPypb+4t+uHeop/Z/Z+nICIoKIjdu3dbtUI2JXopiOcleikpiAZZRKSEoC2Lmqm0rJh7Xp6nIKJslepclV5AGVCffmvOGg3G5WfxoRtkZmURv3cJWdERaLLSkbuVwv3Nj7CvVB+AzOgIEv9cijr1MTalA/BqPwq5q49O9LI0tP5zOb//EtEgi4iUEEp6WdTImGQWH7rBoavpZFduiURhy4EruU0MTAXj4KnoRaNWI3f2wq/nLGSu3mTe/IvH27+hdL/vkNjY8fi3GXi++ykOlRuSfGQ9j7d/Q6mP5umJXl6mjApjiEE9EZESREkVRGgr0O1hiJvYAAAEiUlEQVS7HEuOWkCSr+WXuWCcVvQitbHDrVkv5G6+SCRSHCo3RO7qS/ajGzy5dhIbr3I4Vm2KRG6Da9OeKONuo0yIyT1Xil/0UhIQDbKISAmjpAkinlagM183G/SDcVqjbEr0os5IQpl4Hxvvcigf30HhU1G3TWpjh9zNj5zHd4HnI3opCYguCxGREkhJEUQURTDOmOhFUKuI3zEXp5otUXiWRaPMQubgqjdGauuIkJOp+/1F7QJiDaJBFhEpwfzXgojFh24Qd2ob6RfCyXkcjWO1N/HqMEq3PePyUZKP/YQ6LQG5sxdub36EQ0Aj4GkFuvyiF0HQEL9rHsjkeLQaAoBUYYcm+4neOE3OEyT/1jiGF7cLiDWILgsRERGjaINxMidPXBt3x6lWK73tqrR44nfOw6PFAMqO2oLb2/2I3zEXdUYy8LQCXTkPh6ddQASBhN2LUGck491lEhJZrrFWeJdHGXdbN7cmJwtV0iNsvMsBL3YXEGsQDbKIiIhRtME4h8DGOAQ0QmrvorddnZaA1M4R+0r1kUgkOFRugERhiyr5oW5M/rhk4t7FKBNi8On6BdI8gUGHgEbkxN8h48pxBFUOKcc3ovCpgMKzLPBidwGxBtFlISIiYhRTwTgtNn6VUXiW5cn109hXqk/mjTNI5AoU3k+Dc1kqDTGJmbwZ4M2eUxdIj/gDZAruffuhboxH249xqvE23l0mkfjnUhJ2zcOmVADeHccBL34XEGsQDbKIiIhRTFWg0yKRynAMakH8jjkIqhwkMgVenScgtbHLN4+ST1tU4ej1eMpP2GVyPvsKdSgzaKnB+y96FxBrEF0WIiIiRjFXgQ5ylXXJB1fh23Mm5cZtw7fXTBL3LCIn9la+eRSvdBcQaxANsoiIiFHMVaADyIm9hW3ZGtiWqoJEIsW2VAA2pQPJjI7QjckbjCupopeShGiQRUREjNK1Xm4QTdCoEVQ5oFGDoEFQ5eRWnitVhex7l3Qr4pxHN8mOuYiNTwXdHPmDcSVN9FLSEH3IIiIiRtFWoNuyfD4pxzbq3s+4eBDXJiG4NeuFa9MQHv82E/WTZGT2Lrg26oZ9xdcB08G4kiJ6KYlIhIK0kHmoX7++8NdffxXj4YiIiJQkImOS6fHDqUJVoLNXyNg8KPiV8f+aQyKR/C0IQoHl6kSXhYiIiEnEYNzzRXRZiIiImEXrx52++wpZKvMFhiSS3DS1ye2qvnL+36JANMgiIiIFEhpcgVr+biw5dIODVx8jIVf0ocVOLkUg12c87K3K4sq4kIgGWURExCLEYFzxIxpkERERq/ivK9C9zIhBPREREZESgmiQRUREREoIokEWERERKSGIBllERESkhCAaZBEREZESgmiQRUREREoIokEWERERKSGIBllERESkhGBVtTeJRPIYuFN8hyMiIiLyUlJeEATvggZZZZBFRERERIoP0WUhIiIiUkIQDbKIiIhICUE0yCIiIiIlBNEgi4iIiJQQRIMsIiIiUkIQDbKIiIhICUE0yCIiIiIlBNEgi4iIiJQQRIMsIiIiUkL4f/tvOhqSi7aHAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "pos=nx.layout.spring_layout(G)\n",
    "nx.draw_networkx(G, pos)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-03T06:56:28.290381Z",
     "start_time": "2020-09-03T06:56:27.565471Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0., 1., 1.,  ..., 0., 0., 0.],\n",
      "        [1., 0., 1.,  ..., 0., 0., 0.],\n",
      "        [1., 1., 0.,  ..., 0., 0., 0.],\n",
      "        ...,\n",
      "        [0., 0., 0.,  ..., 0., 0., 0.],\n",
      "        [0., 0., 0.,  ..., 0., 0., 0.],\n",
      "        [0., 0., 0.,  ..., 0., 0., 0.]])\n",
      "[[0. 1. 1. ... 0. 0. 0.]\n",
      " [1. 0. 1. ... 0. 0. 0.]\n",
      " [1. 1. 0. ... 0. 0. 0.]\n",
      " ...\n",
      " [0. 0. 0. ... 0. 0. 0.]\n",
      " [0. 0. 0. ... 0. 0. 0.]\n",
      " [0. 0. 0. ... 0. 0. 0.]]\n",
      "网络直径： 3\n"
     ]
    }
   ],
   "source": [
    "device = 'cuda:4'\n",
    "\n",
    "nnodes = G.number_of_nodes()\n",
    "nedges = G.number_of_edges()\n",
    "\n",
    "A = nx.adjacency_matrix(G)\n",
    "B = nx.to_numpy_array(G)\n",
    "#print(A)\n",
    "#print(B)\n",
    "A = torch.from_numpy(B)\n",
    "A = A.type(torch.float32)\n",
    "print(A)\n",
    "print(B)\n",
    "\n",
    "t = np.log10(nnodes) / np.log10(2 * nedges / nnodes)\n",
    "t = math.ceil(t)\n",
    "print('网络直径：',t)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-16T14:27:08.416321Z",
     "start_time": "2020-08-16T14:27:08.413538Z"
    }
   },
   "source": [
    "# 转移矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-03T06:56:36.935013Z",
     "start_time": "2020-09-03T06:56:31.345249Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.0141, 0.0141, 0.0141,  ..., 0.0141, 0.0141, 0.0141],\n",
      "        [0.0286, 0.0286, 0.0286,  ..., 0.0286, 0.0286, 0.0286],\n",
      "        [0.5000, 0.5000, 0.5000,  ..., 0.5000, 0.5000, 0.5000],\n",
      "        ...,\n",
      "        [0.2500, 0.2500, 0.2500,  ..., 0.2500, 0.2500, 0.2500],\n",
      "        [0.0357, 0.0357, 0.0357,  ..., 0.0357, 0.0357, 0.0357],\n",
      "        [0.0556, 0.0556, 0.0556,  ..., 0.0556, 0.0556, 0.0556]],\n",
      "       device='cuda:4')\n",
      "tensor([[0.0000, 0.0141, 0.0141,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0286, 0.0000, 0.0286,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.5000, 0.5000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        ...,\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000]],\n",
      "       device='cuda:4')\n",
      "tensor([[1.0000, 0.0141, 0.0141,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0286, 1.0000, 0.0286,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.5000, 0.5000, 1.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        ...,\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 1.0000, 0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 1.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 1.0000]],\n",
      "       device='cuda:4')\n"
     ]
    }
   ],
   "source": [
    "transfer_matrix = torch.zeros_like(A,device=device)\n",
    "for i in range(nnodes):\n",
    "    transfer_matrix[i,:] = 1 / G.degree(i)\n",
    "print(transfer_matrix)\n",
    "transfer_matrix = transfer_matrix * A.cuda(4)\n",
    "print(transfer_matrix)\n",
    "#transfer_matrix *= 1 / t\n",
    "transfer_matrix += torch.eye(nnodes,device=device)\n",
    "print(transfer_matrix)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-08-25T10:37:22.872097Z",
     "start_time": "2020-08-25T10:37:22.806647Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.0333, 0.0333, 0.0333,  ..., 0.0333, 0.0333, 0.0333],\n",
      "        [0.0435, 0.0435, 0.0435,  ..., 0.0435, 0.0435, 0.0435],\n",
      "        [0.0263, 0.0263, 0.0263,  ..., 0.0263, 0.0263, 0.0263],\n",
      "        ...,\n",
      "        [1.0000, 1.0000, 1.0000,  ..., 1.0000, 1.0000, 1.0000],\n",
      "        [1.0000, 1.0000, 1.0000,  ..., 1.0000, 1.0000, 1.0000],\n",
      "        [1.0000, 1.0000, 1.0000,  ..., 1.0000, 1.0000, 1.0000]],\n",
      "       device='cuda:4')\n",
      "tensor([[0.0000, 0.0333, 0.0333,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0435, 0.0000, 0.0435,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0263, 0.0263, 0.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        ...,\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 0.0000]],\n",
      "       device='cuda:4')\n",
      "tensor([[1.0000, 0.0333, 0.0333,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0435, 1.0000, 0.0435,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        [0.0263, 0.0263, 1.0000,  ..., 0.0000, 0.0000, 0.0000],\n",
      "        ...,\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 1.0000, 0.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 1.0000, 0.0000],\n",
      "        [0.0000, 0.0000, 0.0000,  ..., 0.0000, 0.0000, 1.0000]],\n",
      "       device='cuda:4')\n"
     ]
    }
   ],
   "source": [
    "transfer_matrix = torch.zeros_like(A,device=device)\n",
    "for i in range(nnodes):\n",
    "    transfer_matrix[i,:] = 1 / G.degree(i + 1)\n",
    "print(transfer_matrix)\n",
    "transfer_matrix = transfer_matrix * A.cuda(4)\n",
    "print(transfer_matrix)\n",
    "#transfer_matrix *= 1 / t\n",
    "transfer_matrix += torch.eye(nnodes,device=device)\n",
    "print(transfer_matrix)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 并行GSO"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-03T06:56:40.960448Z",
     "start_time": "2020-09-03T06:56:40.952479Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "class log(object):\n",
    "    def __init__(self):\n",
    "        self.inf = [];\n",
    "        self.config = [];\n",
    "        \n",
    "t = np.log10(nnodes) / np.log10(2 * nedges / nnodes)\n",
    "t = math.ceil(t)\n",
    "print(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2020-09-03T11:14:26.914292Z",
     "start_time": "2020-09-03T10:09:52.655333Z"
    },
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "0\n",
      "1000\n",
      "\n",
      " 0\n",
      "308 660 662 254370\n",
      "4704.82958984375\n",
      "[29, 87, 307, 833, 2361]\n",
      "percentage: 0.1203125 %\n",
      "4704.82958984375\n",
      "0\n",
      "1000\n",
      "\n",
      " 1\n",
      "331 621 669 254379\n",
      "4715.4443359375\n",
      "[2, 87, 515, 638, 1954]\n",
      "percentage: 0.129296875 %\n",
      "4715.4443359375\n",
      "0\n",
      "1000\n",
      "\n",
      " 2\n",
      "328 622 685 254365\n",
      "4655.9892578125\n",
      "[87, 93, 307, 638, 647]\n",
      "percentage: 0.128125 %\n",
      "4715.4443359375\n",
      "0\n",
      "1000\n",
      "\n",
      " 3\n",
      "311 621 627 254441\n",
      "4652.306640625\n",
      "[29, 87, 135, 819, 4537]\n",
      "percentage: 0.121484375 %\n",
      "4715.4443359375\n",
      "0\n",
      "1000\n",
      "\n",
      " 4\n",
      "324 655 682 254339\n",
      "4669.9716796875\n",
      "[2, 87, 93, 819, 946]\n",
      "percentage: 0.1265625 %\n",
      "4715.4443359375\n",
      "0\n",
      "1000\n",
      "\n",
      " 5\n",
      "301 638 739 254322\n",
      "4835.84326171875\n",
      "[2, 87, 135, 307, 638]\n",
      "percentage: 0.117578125 %\n",
      "4835.84326171875\n",
      "0\n",
      "1000\n",
      "\n",
      " 6\n",
      "300 666 716 254318\n",
      "4753.8271484375\n",
      "[29, 87, 93, 515, 638]\n",
      "percentage: 0.1171875 %\n",
      "4835.84326171875\n",
      "0\n",
      "1000\n",
      "\n",
      " 7\n",
      "323 629 661 254387\n",
      "4816.8896484375\n",
      "[29, 87, 135, 638, 819]\n",
      "percentage: 0.126171875 %\n",
      "4835.84326171875\n",
      "0\n",
      "1000\n",
      "\n",
      " 8\n",
      "324 651 641 254384\n",
      "4707.7431640625\n",
      "[87, 93, 307, 638, 1954]\n",
      "percentage: 0.1265625 %\n",
      "4835.84326171875\n",
      "0\n",
      "1000\n",
      "\n",
      " 9\n",
      "313 687 681 254319\n",
      "4687.64453125\n",
      "[2, 87, 93, 833, 946]\n",
      "percentage: 0.122265625 %\n",
      "4835.84326171875\n",
      "0\n",
      "1000\n",
      "\n",
      " 10\n",
      "337 695 686 254282\n",
      "4832.2958984375\n",
      "[2, 29, 87, 638, 1579]\n",
      "percentage: 0.131640625 %\n",
      "4835.84326171875\n",
      "0\n",
      "1000\n",
      "\n",
      " 11\n",
      "344 628 677 254351\n",
      "4880.36474609375\n",
      "[29, 87, 93, 135, 638]\n",
      "percentage: 0.134375 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 12\n",
      "333 660 663 254344\n",
      "4759.474609375\n",
      "[29, 87, 93, 1954, 3579]\n",
      "percentage: 0.130078125 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 13\n",
      "345 653 674 254328\n",
      "4648.78515625\n",
      "[2, 87, 93, 515, 1771]\n",
      "percentage: 0.134765625 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 14\n",
      "321 656 703 254320\n",
      "4646.70654296875\n",
      "[29, 87, 93, 515, 1954]\n",
      "percentage: 0.125390625 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 15\n",
      "323 673 647 254357\n",
      "4669.9716796875\n",
      "[2, 87, 93, 819, 946]\n",
      "percentage: 0.126171875 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 16\n",
      "283 638 652 254427\n",
      "4595.8056640625\n",
      "[29, 87, 93, 1207, 2525]\n",
      "percentage: 0.110546875 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 17\n",
      "329 635 687 254349\n",
      "4678.7783203125\n",
      "[29, 87, 587, 647, 823]\n",
      "percentage: 0.128515625 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 18\n",
      "325 659 663 254353\n",
      "4733.09228515625\n",
      "[87, 93, 135, 638, 1579]\n",
      "percentage: 0.126953125 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 19\n",
      "292 719 711 254278\n",
      "4847.1015625\n",
      "[2, 87, 135, 3579, 4739]\n",
      "percentage: 0.1140625 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 20\n",
      "327 618 676 254379\n",
      "4680.724609375\n",
      "[29, 87, 510, 638, 819]\n",
      "percentage: 0.127734375 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 21\n",
      "341 617 668 254374\n",
      "4745.62451171875\n",
      "[2, 87, 638, 1579, 1967]\n",
      "percentage: 0.133203125 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 22\n",
      "303 639 634 254424\n",
      "4723.9560546875\n",
      "[87, 93, 135, 638, 4739]\n",
      "percentage: 0.118359375 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 23\n",
      "292 609 730 254369\n",
      "4788.755859375\n",
      "[29, 87, 93, 491, 638]\n",
      "percentage: 0.1140625 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 24\n",
      "319 640 663 254378\n",
      "4658.36181640625\n",
      "[29, 87, 93, 819, 1954]\n",
      "percentage: 0.124609375 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 25\n",
      "333 628 628 254411\n",
      "4646.728515625\n",
      "[87, 93, 435, 638, 819]\n",
      "percentage: 0.130078125 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 26\n",
      "319 594 660 254427\n",
      "4660.3701171875\n",
      "[29, 87, 93, 1093, 1954]\n",
      "percentage: 0.124609375 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 27\n",
      "341 633 662 254364\n",
      "4670.580078125\n",
      "[2, 87, 93, 515, 819]\n",
      "percentage: 0.133203125 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 28\n",
      "315 673 693 254319\n",
      "4827.78125\n",
      "[29, 87, 135, 638, 1207]\n",
      "percentage: 0.123046875 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 29\n",
      "358 677 730 254235\n",
      "4851.384765625\n",
      "[29, 87, 307, 638, 819]\n",
      "percentage: 0.13984375 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 30\n",
      "314 649 690 254347\n",
      "4859.72021484375\n",
      "[29, 87, 307, 491, 638]\n",
      "percentage: 0.12265625 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 31\n",
      "321 648 680 254351\n",
      "4721.900390625\n",
      "[2, 8, 87, 93, 4055]\n",
      "percentage: 0.125390625 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 32\n",
      "330 669 651 254350\n",
      "4802.787109375\n",
      "[8, 29, 87, 135, 638]\n",
      "percentage: 0.12890625 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 33\n",
      "334 657 680 254329\n",
      "4678.72314453125\n",
      "[29, 87, 93, 117, 1866]\n",
      "percentage: 0.13046875 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 34\n",
      "306 635 698 254361\n",
      "4846.60888671875\n",
      "[2, 87, 93, 638, 1579]\n",
      "percentage: 0.11953125 %\n",
      "4880.36474609375\n",
      "0\n",
      "1000\n",
      "\n",
      " 35\n",
      "292 643 651 254414\n",
      "4905.06298828125\n",
      "[2, 29, 87, 135, 638]\n",
      "percentage: 0.1140625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 36\n",
      "321 673 624 254382\n",
      "4655.986328125\n",
      "[29, 76, 87, 93, 1954]\n",
      "percentage: 0.125390625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 37\n",
      "306 660 700 254334\n",
      "4852.28857421875\n",
      "[29, 87, 135, 638, 3083]\n",
      "percentage: 0.11953125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 38\n",
      "320 610 616 254454\n",
      "4706.39111328125\n",
      "[2, 87, 93, 1954, 1967]\n",
      "percentage: 0.125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 39\n",
      "308 643 614 254435\n",
      "4753.8271484375\n",
      "[29, 87, 93, 515, 638]\n",
      "percentage: 0.1203125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 40\n",
      "319 628 700 254353\n",
      "4694.47705078125\n",
      "[52, 87, 93, 491, 638]\n",
      "percentage: 0.124609375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 41\n",
      "364 614 627 254395\n",
      "4612.5419921875\n",
      "[29, 87, 667, 1207, 1967]\n",
      "percentage: 0.1421875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 42\n",
      "327 690 705 254278\n",
      "4665.412109375\n",
      "[29, 87, 93, 1720, 3083]\n",
      "percentage: 0.127734375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 43\n",
      "364 641 632 254363\n",
      "4643.56982421875\n",
      "[87, 93, 515, 4235, 5528]\n",
      "percentage: 0.1421875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 44\n",
      "304 663 659 254374\n",
      "4789.017578125\n",
      "[29, 87, 135, 638, 2408]\n",
      "percentage: 0.11875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 45\n",
      "330 692 716 254262\n",
      "4675.63671875\n",
      "[29, 87, 93, 819, 3083]\n",
      "percentage: 0.12890625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 46\n",
      "348 646 675 254331\n",
      "4736.650390625\n",
      "[2, 87, 93, 1954, 2188]\n",
      "percentage: 0.1359375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 47\n",
      "312 613 666 254409\n",
      "4645.126953125\n",
      "[2, 87, 93, 1495, 6487]\n",
      "percentage: 0.121875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 48\n",
      "307 672 659 254362\n",
      "4692.70703125\n",
      "[29, 87, 638, 1954, 5029]\n",
      "percentage: 0.119921875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 49\n",
      "266 661 644 254429\n",
      "4712.4033203125\n",
      "[29, 87, 93, 135, 5313]\n",
      "percentage: 0.10390625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 50\n",
      "371 628 703 254298\n",
      "4764.302734375\n",
      "[29, 87, 93, 638, 1207]\n",
      "percentage: 0.144921875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 51\n",
      "331 679 658 254332\n",
      "4825.9755859375\n",
      "[2, 87, 135, 638, 2535]\n",
      "percentage: 0.129296875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 52\n",
      "347 637 666 254350\n",
      "4664.0751953125\n",
      "[2, 87, 93, 819, 5868]\n",
      "percentage: 0.135546875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 53\n",
      "334 665 696 254305\n",
      "4905.06298828125\n",
      "[2, 29, 87, 135, 638]\n",
      "percentage: 0.13046875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 54\n",
      "299 635 681 254385\n",
      "4764.302734375\n",
      "[29, 87, 93, 638, 1207]\n",
      "percentage: 0.116796875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 55\n",
      "358 686 684 254272\n",
      "4883.7431640625\n",
      "[2, 87, 135, 638, 4739]\n",
      "percentage: 0.13984375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 56\n",
      "331 627 738 254304\n",
      "4820.31494140625\n",
      "[29, 87, 135, 467, 638]\n",
      "percentage: 0.129296875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 57\n",
      "329 673 713 254285\n",
      "4717.787109375\n",
      "[29, 87, 93, 1954, 3083]\n",
      "percentage: 0.128515625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 58\n",
      "321 631 677 254371\n",
      "4668.845703125\n",
      "[29, 87, 93, 730, 4508]\n",
      "percentage: 0.125390625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 59\n",
      "292 619 650 254439\n",
      "4659.4580078125\n",
      "[29, 87, 93, 1954, 3646]\n",
      "percentage: 0.1140625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 60\n",
      "334 723 723 254220\n",
      "4872.66845703125\n",
      "[29, 87, 307, 638, 1500]\n",
      "percentage: 0.13046875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 61\n",
      "341 653 696 254310\n",
      "4710.14111328125\n",
      "[29, 87, 638, 1661, 1954]\n",
      "percentage: 0.133203125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 62\n",
      "313 642 706 254339\n",
      "4736.40234375\n",
      "[29, 87, 93, 1954, 2750]\n",
      "percentage: 0.122265625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 63\n",
      "326 647 711 254316\n",
      "4636.5859375\n",
      "[87, 135, 638, 819, 1151]\n",
      "percentage: 0.12734375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 64\n",
      "312 598 663 254427\n",
      "4880.36474609375\n",
      "[29, 87, 93, 135, 638]\n",
      "percentage: 0.121875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 65\n",
      "314 695 668 254323\n",
      "4705.7744140625\n",
      "[29, 87, 638, 1967, 3083]\n",
      "percentage: 0.12265625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 66\n",
      "336 609 667 254388\n",
      "4905.06298828125\n",
      "[2, 29, 87, 135, 638]\n",
      "percentage: 0.13125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 67\n",
      "320 642 663 254375\n",
      "4735.24462890625\n",
      "[29, 76, 87, 93, 307]\n",
      "percentage: 0.125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 68\n",
      "355 615 674 254356\n",
      "4818.1484375\n",
      "[2, 29, 87, 93, 1954]\n",
      "percentage: 0.138671875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 69\n",
      "317 654 699 254330\n",
      "4793.02392578125\n",
      "[29, 87, 135, 347, 638]\n",
      "percentage: 0.123828125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 70\n",
      "342 627 702 254329\n",
      "4685.7822265625\n",
      "[29, 87, 135, 819, 1954]\n",
      "percentage: 0.13359375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 71\n",
      "316 663 649 254372\n",
      "4840.5869140625\n",
      "[2, 87, 135, 638, 4987]\n",
      "percentage: 0.1234375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 72\n",
      "337 668 697 254298\n",
      "4827.78125\n",
      "[29, 87, 135, 638, 1207]\n",
      "percentage: 0.131640625 %\n",
      "4905.06298828125\n",
      "0\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1000\n",
      "\n",
      " 73\n",
      "355 636 636 254373\n",
      "4831.64453125\n",
      "[29, 87, 135, 307, 638]\n",
      "percentage: 0.138671875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 74\n",
      "322 599 670 254409\n",
      "4831.64453125\n",
      "[29, 87, 135, 307, 638]\n",
      "percentage: 0.12578125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 75\n",
      "319 620 688 254373\n",
      "4658.83203125\n",
      "[2, 87, 93, 1207, 1801]\n",
      "percentage: 0.124609375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 76\n",
      "334 669 728 254269\n",
      "4811.53515625\n",
      "[29, 87, 93, 638, 1954]\n",
      "percentage: 0.13046875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 77\n",
      "311 649 650 254390\n",
      "4845.40234375\n",
      "[2, 87, 307, 638, 946]\n",
      "percentage: 0.121484375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 78\n",
      "313 703 650 254334\n",
      "4658.36083984375\n",
      "[29, 87, 93, 819, 1954]\n",
      "percentage: 0.122265625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 79\n",
      "301 628 663 254408\n",
      "4680.35400390625\n",
      "[87, 135, 638, 1954, 4914]\n",
      "percentage: 0.117578125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 80\n",
      "329 603 661 254407\n",
      "4756.1796875\n",
      "[2, 87, 307, 819, 946]\n",
      "percentage: 0.128515625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 81\n",
      "360 646 667 254327\n",
      "4905.06298828125\n",
      "[2, 29, 87, 135, 638]\n",
      "percentage: 0.140625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 82\n",
      "331 616 654 254399\n",
      "4755.3505859375\n",
      "[29, 87, 93, 307, 819]\n",
      "percentage: 0.129296875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 83\n",
      "292 659 752 254297\n",
      "4769.99658203125\n",
      "[29, 87, 93, 638, 819]\n",
      "percentage: 0.1140625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 84\n",
      "337 633 695 254335\n",
      "4816.8896484375\n",
      "[29, 87, 135, 638, 819]\n",
      "percentage: 0.131640625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 85\n",
      "321 700 656 254323\n",
      "4892.7021484375\n",
      "[2, 87, 135, 638, 1579]\n",
      "percentage: 0.125390625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 86\n",
      "330 672 634 254364\n",
      "4721.0859375\n",
      "[2, 87, 93, 1801, 3083]\n",
      "percentage: 0.12890625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 87\n",
      "327 684 622 254367\n",
      "4790.12255859375\n",
      "[2, 87, 381, 638, 4506]\n",
      "percentage: 0.127734375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 88\n",
      "346 638 637 254379\n",
      "4670.40966796875\n",
      "[29, 87, 93, 1207, 3083]\n",
      "percentage: 0.13515625 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 89\n",
      "311 661 667 254361\n",
      "4753.8271484375\n",
      "[29, 87, 93, 515, 638]\n",
      "percentage: 0.121484375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 90\n",
      "302 651 673 254374\n",
      "4752.4013671875\n",
      "[87, 135, 638, 751, 1579]\n",
      "percentage: 0.11796875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 91\n",
      "336 623 732 254309\n",
      "4859.72021484375\n",
      "[29, 87, 307, 491, 638]\n",
      "percentage: 0.13125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 92\n",
      "323 697 674 254306\n",
      "4903.28466796875\n",
      "[29, 87, 93, 307, 638]\n",
      "percentage: 0.126171875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 93\n",
      "319 593 604 254484\n",
      "4671.8623046875\n",
      "[87, 135, 638, 4186, 4739]\n",
      "percentage: 0.124609375 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 94\n",
      "270 641 616 254473\n",
      "4827.4482421875\n",
      "[2, 87, 135, 4400, 4914]\n",
      "percentage: 0.10546875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 95\n",
      "323 628 721 254328\n",
      "4886.4921875\n",
      "[2, 87, 135, 381, 638]\n",
      "percentage: 0.126171875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 96\n",
      "320 616 644 254420\n",
      "4800.4921875\n",
      "[2, 29, 87, 344, 819]\n",
      "percentage: 0.125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 97\n",
      "320 651 685 254344\n",
      "4852.28857421875\n",
      "[29, 87, 135, 638, 3083]\n",
      "percentage: 0.125 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 98\n",
      "307 624 653 254416\n",
      "4719.1669921875\n",
      "[87, 93, 638, 3579, 4914]\n",
      "percentage: 0.119921875 %\n",
      "4905.06298828125\n",
      "0\n",
      "1000\n",
      "\n",
      " 99\n",
      "330 652 719 254299\n",
      "4829.1650390625\n",
      "[29, 87, 135, 530, 638]\n",
      "percentage: 0.12890625 %\n",
      "4905.06298828125\n"
     ]
    }
   ],
   "source": [
    "#torch.manual_seed(2050)\n",
    "bs = 128\n",
    "n = nnodes\n",
    "init_tau = 3\n",
    "final_tau = 0.1\n",
    "\n",
    "#mu = 3\n",
    "#sigma = 5\n",
    "#decay = (init_tau - final_tau) / epoch\n",
    "\n",
    "t = np.log10(nnodes) / np.log10(2 * nedges / nnodes)\n",
    "t = math.ceil(t)\n",
    "print(t)\n",
    "\n",
    "ones = torch.ones(bs, nnodes, device=device)\n",
    "lr = 1\n",
    "\n",
    "eta0 = 5\n",
    "eta1 = 1\n",
    "num = 5\n",
    "exp = 2\n",
    "epoch = 2000\n",
    "instance = 100\n",
    "\n",
    "tau = init_tau\n",
    "a = b = c = d = 0\n",
    "ll = log()\n",
    "lins = []\n",
    "\n",
    "x = torch.randn(bs, n, 1, device=device) * 1e-5\n",
    "x.requires_grad = True\n",
    "optimizer = torch.optim.Adam([x], lr=lr)\n",
    "\n",
    "for _ in range(instance):\n",
    "    ll = log()\n",
    "    optimizer.zero_grad()\n",
    "    x = torch.randn(bs, n, 1, device=device) * 1e-5\n",
    "    x.requires_grad = True\n",
    "    optimizer = torch.optim.Adam([x], lr=lr)\n",
    "    cost = torch.zeros(bs, device=device)\n",
    "    a = b = c = d = 0\n",
    "    for i in range(epoch):\n",
    "        optimizer.zero_grad()\n",
    "        probs = torch.empty(bs, n, 2, device=device)\n",
    "        p = torch.sigmoid(x)\n",
    "        probs[:, :, 0] = p.squeeze()\n",
    "        probs[:, :, -1] = 1-probs[:, :, 0]\n",
    "        logits = torch.log(probs+1e-10)\n",
    "        s = gumbel_softmax_3d(logits, tau=tau, hard=True)[:, :, 0]\n",
    "        #tau -= decay\n",
    "        #s = torch.unsqueeze(s, -1)  # size [bs, n, 1]\n",
    "        #print(s)\n",
    "        #print(s.size())\n",
    "        \n",
    "        restmp = s\n",
    "        \n",
    "        #restmp = s.unsqueeze(0)\n",
    "        #print(restmp)\n",
    "        #print(restmp.size())\n",
    "        #print(transfer_matrix.size())\n",
    "        #sdfs\n",
    "        #for i in range(bs):\n",
    "            #restmp[i,:] = restmp[i,:] / torch.sum(restmp, 1)[i]\n",
    "        #print(restmp)\n",
    "        #print(torch.sum(restmp, 1))\n",
    "        #print(torch.sum(restmp))\n",
    "    \n",
    "        #print(transfer_matrix)\n",
    "        #print(restmp.size())\n",
    "    \n",
    "        for j in range(t):\n",
    "            res = torch.mm(restmp, transfer_matrix)\n",
    "            #print(i, \"\\t\", res)\n",
    "            res = torch.min(res, ones)\n",
    "            #print(torch.sum(res))\n",
    "            #print(torch.var(res))\n",
    "            restmp = res\n",
    "            #print(restmp)\n",
    "            #print(torch.sum(restmp, 1))\n",
    "            #print(torch.sum(restmp))\n",
    "        \n",
    "        #print('restmp:',restmp)\n",
    "        \n",
    "        \n",
    "        cost_ = torch.sum(s, dim=1)\n",
    "        #print(cost_)\n",
    "\n",
    "\n",
    "        cost_ = eta0 * ((cost_ - num) ** exp)\n",
    "        cost = torch.sum(cost_)\n",
    "    \n",
    "        inf = torch.sum(restmp)\n",
    "    \n",
    "        loss = -inf + eta1 * cost\n",
    "    \n",
    "        #print(i,':')\n",
    "        #print('loss:',loss.item())\n",
    "        #print('inf:',inf.item())\n",
    "        #print('cost:',cost.item())\n",
    "        \n",
    "        with torch.no_grad():\n",
    "            constraint = cost_.cpu().numpy()\n",
    "            #print(constraint)\n",
    "            idx0 = np.argwhere(constraint == 0)\n",
    "            idx1 = np.argwhere(constraint == eta0)\n",
    "            idx2 = np.argwhere(constraint == eta0 * (2 ** exp))\n",
    "\n",
    "            idc0 = len(idx0)\n",
    "            idc1 = len(idx1)\n",
    "            idc2 = len(idx2)\n",
    "\n",
    "            idce = bs - (idc0 + idc1 + idc2)\n",
    "            a += idc0\n",
    "            b += idc1\n",
    "            c += idc2\n",
    "            d += idce\n",
    "            \n",
    "            if idc0 != 0:\n",
    "                #for k in idx0:\n",
    "                #    k = k.item()\n",
    "                #    E_now = torch.sum(restmp[k, :])\n",
    "                #    #print(E_now)\n",
    "                #    if E_now >= maxinf:\n",
    "                #        maxinf = E_now.item()\n",
    "                #        constraint = s[k, :].cpu().numpy()\n",
    "                #        idx = np.argwhere(constraint == 1)\n",
    "                Ei = torch.sum(restmp[idx0, :], dim=2).squeeze()\n",
    "                Emax = Ei.max().item()\n",
    "                Eindex = idx0[torch.argmax(Ei)]\n",
    "                Es = s[Eindex, :].squeeze().cpu().numpy()\n",
    "                idx = np.argwhere(Es == 1)\n",
    "\n",
    "                ll.inf.append(Emax)\n",
    "                #constraint = s.cpu().numpy()\n",
    "                #idx = np.argwhere(constraint == 1)\n",
    "                idx = idx.reshape(len(idx)).tolist()\n",
    "                ll.config.append(idx)\n",
    "                #print('config:',s.cpu().numpy())\n",
    "        \n",
    "        #print(i)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "    \n",
    "        if i % 1000 == 0:\n",
    "            print(i)\n",
    "\n",
    "    #print(ll.inf.sort())\n",
    "    print('\\n',_)\n",
    "    print(a,b,c,d)\n",
    "    print(max(ll.inf))\n",
    "    lins.append(max(ll.inf))\n",
    "    print(ll.config[ll.inf.index(max(ll.inf))])\n",
    "    print('percentage:',100 * a / (bs * epoch),'%')\n",
    "    print(max(lins))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
